Javascript 当requestAnimationFrame调用-ES6时,画布无法找到上下文
我正在试验基于类的代码。我为画布创建一个类,并向其传递一个组件,然后对其进行渲染。问题是,当浏览器请求动画帧时,上下文将丢失,并且变得未定义。我正在寻找一个解释,为什么会出现这种情况 我不关心最佳实践,只是想弄清楚为什么失去了上下文 我已经附加了一个链接到codepen上的示例 以下是JS代码:Javascript 当requestAnimationFrame调用-ES6时,画布无法找到上下文,javascript,css,ecmascript-6,babeljs,Javascript,Css,Ecmascript 6,Babeljs,我正在试验基于类的代码。我为画布创建一个类,并向其传递一个组件,然后对其进行渲染。问题是,当浏览器请求动画帧时,上下文将丢失,并且变得未定义。我正在寻找一个解释,为什么会出现这种情况 我不关心最佳实践,只是想弄清楚为什么失去了上下文 我已经附加了一个链接到codepen上的示例 以下是JS代码: class Canvas { constructor() { this.canvas = document.getElementById('canvas'); this.conte
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
}));
类画布{
构造函数(){
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;
此参数为.components=[];
}
画(){
this.context.clearRect(0,0,this.width,this.height);
this.context.globalCompositeOperation='hard light';
this.components.map(=>u.render());
window.requestAnimationFrame(this.draw);
}
听众(){
window.addEventListener('resize',()=>{
this.width=this.canvas.width=window.innerHeight;
this.height=this.canvas.height=window.innerWidth;
},假);
}
init(){
this.listeners();
这个.draw();
}
}
类Utils{
随机数(最大值,最小值){
返回Math.floor(max*Math.random())+min;
}
颜色(不透明度){
返回`hsla(${this.randomNum(360,1)},70%,60%,${opacity})`;
}
}
const utils=新utils();
const_canvas=新画布();
班级明星{
构造函数{
this.total=uu.total;
this.spawn=[];
这个z=300;
this.canvas=ux.canvas;
this.xw=this.canvas.width*this.z;
this.xh=this.canvas.height*this.z;
}
创建(){
while(this.spawn.lengththis.canvas.width/2 | | y<-this.canvas.height/2 | | y>this.canvas.height/2 | | t.pos[2]<0){
this.spawn.splice(i,1);
--一,;
继续;
}
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、 位置[0]+=t.vel[0];
t、 位置[1]+=t.vel[1];
t、 位置[2]+=t.vel[2];
this.canvas.context.fill();
}
}
render(){
这个。create();
this.canvas.context.save();
this.canvas.context.translate(this.canvas.width/2,this.canvas.height/2);
这个.draw();
this.canvas.context.restore();
}
}
_画布。组件。推送(新星星)({
画布:_画布,
总数:200
}));
当您通过窗口调用draw()
时,requestAnimationFrame(this.draw)
中的作用域绑定到draw()
窗口,而不是画布
。尝试显式绑定作用域,如下所示:
window.requestAnimationFrame(this.draw.bind(this));
真是太棒了。谢谢。或者,因为我们还是使用ES 6,()=>this.draw()
。顺便说一句:绑定的不是范围,而是this
的值。