取消对象方法内部的动画帧不起作用

cancelAnimationFrame inside of object method not working

本文关键字:动画 不起作用 内部 对象 方法 取消      更新时间:2023-09-26
cancelAnimationFrame()

对象方法中调用时似乎不起作用。我尝试将this值绑定到回调函数(如 MDN 上演示的 setTimeout ),但在使用 cancelAnimationFrame() 时收到 TypeError 。然后,我尝试将this值设置为名为 _this 的局部变量并再次调用 cancelAnimationFrame()。那一次,我没有收到错误,但动画本身仍在播放。如何取消动画?

我已经在下面重新创建了我遇到的问题。如果打开控制台窗口,您将看到动画仍在运行。

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();

看来你在这里错过了两件事。首先,this.animation = window.requestAnimationFrame(this.play.bind(this));行在调用时始终调用play()。与您可能认为的相反,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);
  }
};

。但关键是,它在问题中描述的用例中没有用。