当id不断增加时,cancelAnimationFrame如何工作?

时间:2019-04-29 19:31:13

标签: javascript settimeout setinterval requestanimationframe cancelanimationframe

背景

使用setInterval或setTimeout时,我们会收到一个ID来取消/清除操作。

setInterval / setTimeout:

const timeoutId = setTimeout(() => {clearTimeout(timeoutId)}, 1000);
const intervalId = setInterval(() => {clearInterval(intervalId)}, 1000);

requestAnimationFrame: 使用raf时,对于步骤的每次迭代,我们都会重置rafId,而我们仅对最新的rafId调用cancelAnimationFrame?

let rafId;

function step(timestamp) {
  rafId = requestAnimationFrame(step);
  console.log(timestamp, rafId)
  if(timestamp >= 1000) {
    cancelAnimationFrame(rafId);
  }
}
rafId = requestAnimationFrame(step);

问题:rafId不断更新时,cancelAnimationFrame如何知道关闭对requestAnimationFrame的所有先前调用?

我猜想cancelAnimationFrame可以使用frameId并关闭其后面的所有内容。

如果是这样,它将如何与多个requestAnimationFrames(因为它们将共享一个frameId)一起使用

1 个答案:

答案 0 :(得分:1)

的确,requestAnimationFrame返回的ID不断增加一个-但这并不重要。为了使请求保持“活动”状态,您需要在回调中重新请求它。 让我们看看上次触发回调函数步骤会发生什么:

function step(timestamp) {
  console.log("before " + rafId);
  rafId = requestAnimationFrame(step);
  console.log("after " + rafId);
  if (timestamp >= 1000) {
    cancelAnimationFrame(rafId);
  }
}
rafId = requestAnimationFrame(step);

如果您查看控制台的最后两行,则类似于:

50岁之前

51之后

这意味着从上次回调返回的id为50,现在我们正在请求一个新的animationframe,该ID为51。这一次,尽管我们的if条件为true,所以取消了对id 51的请求。调用回调函数后,对ID 50的请求已完成,因此无需取消它。