Canvas 调用 requestAnimationFrame 时无法找到上下文 - ES6
Canvas unable to find context when requestAnimationFrame is called - ES6
我正在试验基于 class 的代码。我为 canvas 创建了一个 class 并将一个组件传递给它,然后将其渲染。问题是,当浏览器请求动画帧时,上下文丢失,并变得未定义。我正在寻找为什么会这样的解释。
我不关心最佳实践,只是想弄清楚上下文丢失的原因。
我已将 link 附加到 codepen 上的示例。
http://codepen.io/BrianDGLS/pen/BoJorM?editors=001
这里是JS代码:
class Canvas {
constructor() {
this.canvas = document.getElementById('canvas');
this.context = this.canvas.getContext('2d');
this.width = this.canvas.width = window.innerHeight;
this.height = this.canvas.height = window.innerWidth;
this.components = [];
}
draw() {
this.context.clearRect(0, 0, this.width, this.height);
this.context.globalCompositeOperation = 'hard-light';
this.components.map(_ => _.render());
window.requestAnimationFrame(this.draw);
}
listeners() {
window.addEventListener('resize', () => {
this.width = this.canvas.width = window.innerHeight;
this.height = this.canvas.height = window.innerWidth;
}, false);
}
init() {
this.listeners();
this.draw();
}
}
class Utils {
randomNum(max, min) {
return Math.floor(max * Math.random()) + min;
}
color(opacity) {
return `hsla(${this.randomNum(360, 1)}, 70%, 60%, ${opacity})`;
}
}
const utils = new Utils();
const _canvas = new Canvas();
class Stars {
constructor(_) {
this.total = _.total;
this.spawn = [];
this.z = 300;
this.canvas = _.canvas;
this.xw = this.canvas.width * this.z;
this.xh = this.canvas.height * this.z;
}
create() {
while (this.spawn.length < this.total) {
this.spawn.push({
pos: [this.xw * Math.random() - this.canvas.width / 2 * this.z, this.xh * Math.random() - this.canvas.height / 2 * this.z, this.z],
vel: [0, 0, -2],
r: utils.randomNum(500, 100),
color: utils.color(1)
});
}
}
draw() {
for (let i = 0; i < this.spawn.length; ++i) {
let t = this.spawn[i];
let x = t.pos[0] / t.pos[2];
let y = t.pos[1] / t.pos[2];
if (x < -this.canvas.width / 2 || x > this.canvas.width / 2 || y < -this.canvas.height / 2 || y > this.canvas.height / 2 || t.pos[2] < 0) {
this.spawn.splice(i, 1);
--i;
continue;
}
this.canvas.context.beginPath();
this.canvas.context.fillStyle = t.color;
this.canvas.context.arc(x, y, t.r / t.pos[2], 0, Math.PI * 2, false);
t.pos[0] += t.vel[0];
t.pos[1] += t.vel[1];
t.pos[2] += t.vel[2];
this.canvas.context.fill();
}
}
render() {
this.create();
this.canvas.context.save();
this.canvas.context.translate(this.canvas.width / 2, this.canvas.height / 2);
this.draw();
this.canvas.context.restore();
}
}
_canvas.components.push(new Stars({
canvas: _canvas,
total: 200
}));
当您通过 window.requestAnimationFrame(this.draw)
调用 draw()
时,draw()
中的范围绑定到 window
而不是 Canvas
。尝试像这样显式绑定范围:
window.requestAnimationFrame(this.draw.bind(this));
我正在试验基于 class 的代码。我为 canvas 创建了一个 class 并将一个组件传递给它,然后将其渲染。问题是,当浏览器请求动画帧时,上下文丢失,并变得未定义。我正在寻找为什么会这样的解释。
我不关心最佳实践,只是想弄清楚上下文丢失的原因。
我已将 link 附加到 codepen 上的示例。
http://codepen.io/BrianDGLS/pen/BoJorM?editors=001
这里是JS代码:
class Canvas {
constructor() {
this.canvas = document.getElementById('canvas');
this.context = this.canvas.getContext('2d');
this.width = this.canvas.width = window.innerHeight;
this.height = this.canvas.height = window.innerWidth;
this.components = [];
}
draw() {
this.context.clearRect(0, 0, this.width, this.height);
this.context.globalCompositeOperation = 'hard-light';
this.components.map(_ => _.render());
window.requestAnimationFrame(this.draw);
}
listeners() {
window.addEventListener('resize', () => {
this.width = this.canvas.width = window.innerHeight;
this.height = this.canvas.height = window.innerWidth;
}, false);
}
init() {
this.listeners();
this.draw();
}
}
class Utils {
randomNum(max, min) {
return Math.floor(max * Math.random()) + min;
}
color(opacity) {
return `hsla(${this.randomNum(360, 1)}, 70%, 60%, ${opacity})`;
}
}
const utils = new Utils();
const _canvas = new Canvas();
class Stars {
constructor(_) {
this.total = _.total;
this.spawn = [];
this.z = 300;
this.canvas = _.canvas;
this.xw = this.canvas.width * this.z;
this.xh = this.canvas.height * this.z;
}
create() {
while (this.spawn.length < this.total) {
this.spawn.push({
pos: [this.xw * Math.random() - this.canvas.width / 2 * this.z, this.xh * Math.random() - this.canvas.height / 2 * this.z, this.z],
vel: [0, 0, -2],
r: utils.randomNum(500, 100),
color: utils.color(1)
});
}
}
draw() {
for (let i = 0; i < this.spawn.length; ++i) {
let t = this.spawn[i];
let x = t.pos[0] / t.pos[2];
let y = t.pos[1] / t.pos[2];
if (x < -this.canvas.width / 2 || x > this.canvas.width / 2 || y < -this.canvas.height / 2 || y > this.canvas.height / 2 || t.pos[2] < 0) {
this.spawn.splice(i, 1);
--i;
continue;
}
this.canvas.context.beginPath();
this.canvas.context.fillStyle = t.color;
this.canvas.context.arc(x, y, t.r / t.pos[2], 0, Math.PI * 2, false);
t.pos[0] += t.vel[0];
t.pos[1] += t.vel[1];
t.pos[2] += t.vel[2];
this.canvas.context.fill();
}
}
render() {
this.create();
this.canvas.context.save();
this.canvas.context.translate(this.canvas.width / 2, this.canvas.height / 2);
this.draw();
this.canvas.context.restore();
}
}
_canvas.components.push(new Stars({
canvas: _canvas,
total: 200
}));
当您通过 window.requestAnimationFrame(this.draw)
调用 draw()
时,draw()
中的范围绑定到 window
而不是 Canvas
。尝试像这样显式绑定范围:
window.requestAnimationFrame(this.draw.bind(this));