为什么我需要cancelAnimationFrame()

时间:2014-11-24 15:31:22

标签: javascript animation

我不明白为什么API包含cancelAnimationFrame(),因为 我可以通过设置continue变量来停止动画:

function draw(timestamp) {
  if (continue == true) { requestAnimationFrame(draw); }
}

所以问题是在什么情况下我应该使用cancelAnimationFrame()?

2 个答案:

答案 0 :(得分:2)

首先,一个重要的参考点。 A(注明日期)(候选推荐)规范:http://www.w3.org/TR/animation-timing/#definitions

  

与每个Document相关联的是一个动画帧请求回调列表,它是一个元组列表。 handle是一个整数^[long],用于唯一标识列表中的条目。 callback是一个FrameRequestCallback对象。最初,Document的动画帧请求回调列表为空。

另外,请记住,这些规范的目标受众是用户代理开发人员。正是在这些规范的实现中,用户代理为我们(应用程序开发人员)提供了一个API来与之交互。

请注意上面的每个文档 情绪;您可以在window 上下文 中包含多个文档。您可以在浏览上下文中包含多个 上下文

那么,这与每个文档有什么关系?那么,(推荐)规范引用了过程模型,它基本上将所有这些列表转储到一个空列表中,并对保留的结果执行回调调用算法 '列表..但是,再次,这可能不是我们作为应用程序开发人员的关注; *我认为,作为应用开发者,我们不会在我们自己的window 上下文的多个文档中及其中跟踪和维护Document.FrameRequestList实例。我们只需与API进行交互,可在window上访问。

现在,让我们总结requestAnimationFrame(<function>)生效的内容, AND 返回的内容

致电requestAnimationFrame并提供function作为回调,添加条目<handler,FrameRequestCallback><long, "an object, with a cancelled member, that encapsulates your function"> )进入动画帧请求回调列表 requestAnimationFrame会返回Handler [long]

根据上述规范(http://www.w3.org/TR/animation-timing/#dom-windowanimationtiming-cancelanimationframe),

  

cancelAnimationFrame方法用于取消先前制定的安排动画帧更新的请求。

可以推断,通过调用cancelAnimationFrame并提供(可能是之前存储的)handle作为参数,您 删除 条目来自动画帧请求回调列表并非如此。

  

当调用cancelAnimationFrame(handle)时,用户代理必须将已取消的标记设置为true,以便在 文档 上注册的回调 handle 句柄。无论回调是否在动画帧请求回调列表中,都会设置已取消标志。如果没有给定句柄的回调,则此函数不执行任何操作。

因此,handle中提供的cancelAnimationFrame不会修改列表。它将取消的标志设置为true'在回调'..这确实使它无法运行。这是合理的,因为前面提到的(上面)处理模型


那么,对于你的问题(以及关于你的问题的特定评论)跳过添加文件的动画帧请求回调列表的条目,使用{{1} }不会保留现有的requestAnimationFrame条目(或已取消标志为false的现有条目)。需要考虑“更大”的上下文和处理模型(包括文档页面可见性属性)。

在您的问题中提到了一个评论,即您可能希望取消计划框架请求的特定场景 - 但更好的理由是针对无意的方面和考虑因素。

简而言之,如果您要使用API​​来请求执行回调的帧更新,请使用API​​取消/停止所述更新请求并停止回调。

答案 1 :(得分:0)

FWIW并完成接受的答案:

我来这里是为了找出用requestAnimationFrame调度的函数在执行时使从DOM中已经删除(也称为卸载)的元素发生突变,是否会引发错误。否,即:

let el = document.getElementById('element'); 
setTimeout(() => el.remove(), 20); 
setTimeout(() => {
  el.style.transform = 'scale(2)'
  console.log(el instanceof HTMLElement) // el is kept in memory but removed from the DOM
, 40) // true`. 

总而言之,您应该使用cancelAnimationFrame来防止由requestAnimationFrame自动调度的函数带来的副作用,并且您可以选择通过避免执行该函数来对其进行(微)优化,即使它没有副作用。