对象方法内的 cancelAnimationFrame 不起作用
cancelAnimationFrame inside of object method not working
cancelAnimationFrame()
在对象的方法内部调用时似乎不起作用。我已尝试将 this
值绑定到回调函数(as demonstrated on MDN 和 setTimeout
),但在使用 cancelAnimationFrame()
时收到 TypeError。然后我尝试将 this
值设置为一个名为 _this
的局部变量并再次调用 cancelAnimationFrame()
。那一次,我没有收到错误,但动画本身仍在播放。如何取消动画?
我已经在下面重现了我遇到的问题。如果你打开控制台 window,你会看到动画仍然是 运行。
function WhyWontItCancel() {
this.canvas = document.createElement("canvas");
this.canvas.width = 200;
this.canvas.height = 10;
document.body.appendChild(this.canvas);
this.draw = this.canvas.getContext("2d");
this.draw.fillStyle = "#f00";
this.position = 0;
};
WhyWontItCancel.prototype.play = function() {
if (this.position <= 190) {
this.draw.clearRect(0, 0, 400, 10);
this.draw.fillRect(this.position, 0, 10, 10);
this.position += 2;
} else {
//window.cancelAnimationFrame(this.animation.bind(this));
var _this = this;
window.cancelAnimationFrame(_this.animation);
console.log("still running");
}
this.animation = window.requestAnimationFrame(this.play.bind(this));
};
var animation = new WhyWontItCancel();
animation.play();
看来您在这里漏掉了两件事。首先,当 play()
被调用时,this.animation = window.requestAnimationFrame(this.play.bind(this));
行被调用 always。与您的想法相反,cancelAnimationFrame
仅删除先前请求的 RAF 调用。严格来说,这里甚至没有必要。其次,您不必绑定每个 RAF 调用;你可能只做一次:
function AnimatedCanvas() {
this.canvas = document.createElement("canvas");
this.canvas.width = 200;
this.canvas.height = 10;
document.body.appendChild(this.canvas);
this.draw = this.canvas.getContext("2d");
this.draw.fillStyle = "#f00";
this.position = 0;
this.play = this.play.bind(this); // takes `play` from prototype object
};
AnimatedCanvas.prototype.play = function() {
if (this.position <= 190) {
this.draw.clearRect(0, 0, 400, 10);
this.draw.fillRect(this.position, 0, 10, 10);
this.position += 2;
this.animationId = window.requestAnimationFrame(this.play);
}
};
您可能希望将取消添加到原型中以便能够停止动画,例如:
AnimatedCanvas.prototype.cancel = function() {
if (this.animationId) {
window.cancelAnimationFrame(this.animationId);
}
};
...但关键是,它在问题中描述的用例中没有用。
cancelAnimationFrame()
在对象的方法内部调用时似乎不起作用。我已尝试将 this
值绑定到回调函数(as demonstrated on MDN 和 setTimeout
),但在使用 cancelAnimationFrame()
时收到 TypeError。然后我尝试将 this
值设置为一个名为 _this
的局部变量并再次调用 cancelAnimationFrame()
。那一次,我没有收到错误,但动画本身仍在播放。如何取消动画?
我已经在下面重现了我遇到的问题。如果你打开控制台 window,你会看到动画仍然是 运行。
function WhyWontItCancel() {
this.canvas = document.createElement("canvas");
this.canvas.width = 200;
this.canvas.height = 10;
document.body.appendChild(this.canvas);
this.draw = this.canvas.getContext("2d");
this.draw.fillStyle = "#f00";
this.position = 0;
};
WhyWontItCancel.prototype.play = function() {
if (this.position <= 190) {
this.draw.clearRect(0, 0, 400, 10);
this.draw.fillRect(this.position, 0, 10, 10);
this.position += 2;
} else {
//window.cancelAnimationFrame(this.animation.bind(this));
var _this = this;
window.cancelAnimationFrame(_this.animation);
console.log("still running");
}
this.animation = window.requestAnimationFrame(this.play.bind(this));
};
var animation = new WhyWontItCancel();
animation.play();
看来您在这里漏掉了两件事。首先,当 play()
被调用时,this.animation = window.requestAnimationFrame(this.play.bind(this));
行被调用 always。与您的想法相反,cancelAnimationFrame
仅删除先前请求的 RAF 调用。严格来说,这里甚至没有必要。其次,您不必绑定每个 RAF 调用;你可能只做一次:
function AnimatedCanvas() {
this.canvas = document.createElement("canvas");
this.canvas.width = 200;
this.canvas.height = 10;
document.body.appendChild(this.canvas);
this.draw = this.canvas.getContext("2d");
this.draw.fillStyle = "#f00";
this.position = 0;
this.play = this.play.bind(this); // takes `play` from prototype object
};
AnimatedCanvas.prototype.play = function() {
if (this.position <= 190) {
this.draw.clearRect(0, 0, 400, 10);
this.draw.fillRect(this.position, 0, 10, 10);
this.position += 2;
this.animationId = window.requestAnimationFrame(this.play);
}
};
您可能希望将取消添加到原型中以便能够停止动画,例如:
AnimatedCanvas.prototype.cancel = function() {
if (this.animationId) {
window.cancelAnimationFrame(this.animationId);
}
};
...但关键是,它在问题中描述的用例中没有用。