动画帧渲染后的javascript运行函数

Posted

技术标签:

【中文标题】动画帧渲染后的javascript运行函数【英文标题】:javascript run function after animation frame renders 【发布时间】:2017-05-23 01:21:56 【问题描述】:

据我了解,您的动画需要 60fps 才能使动画看起来流畅。基本上我要做的是在帧开始时进行繁重的计算,所以到渲染实际发生时,已经没有太多工作要做了。

我知道您可以在重绘屏幕之前使用 window.requestAnimationFrame 来运行一个函数。但是,如果该功能需要很长时间,那将导致抽搐效果。有没有办法在屏幕重绘后立即运行函数?

我尝试过这样的事情,但它失败了:

window.requestAnimationFrame(do_before);

do_before()            
     window.setTimeout(do_after, 1);


do_after()
    //code to execute after animation frame

正如您在下图中看到的那样,do_after 代码仍在同一帧中执行,因此我有时会出现长帧:

Link to image

有没有办法让 do_after() 在屏幕完成绘制后运行?

提前致谢

【问题讨论】:

【参考方案1】:

实际上,您问题的代码是正确的。 setTimeout(do_after) 在 Chrome 和 Safari 中就足够了(我还没有在其他浏览器中测试过)。它使浏览器在没有其他任务时执行该功能。

如果你想从requestAnimationFrame回调内部延迟执行,只需调用setTimeout(do_after),回调将在帧刷新后立即执行:

requestAnimationFrame(() => 
  do_before();
  setTimeout(do_after);
);

如果您想从其他地方延迟执行(例如点击处理程序或 AJAX 响应处理程序),请先调用requestAnimationFrame,然后再调用setTimeout

document.addEventListener('click', () => 
  do_before();
  requestAnimationFrame(() => 
    setTimeout(do_after);
  );
);

不幸的是,我还没有找到在下一帧开始时执行回调的通用方法,因为有no straightforward way 可以知道代码是否在requestAnimationFrame 处理程序中执行。你可以使用a trick来解决它

如果您需要在任何帧刷新后立即执行回调,请使用第二种方法 (requestAnimationFrame + setTimeout)。这可能会导致在运行回调之前空闲整个动画帧。

【讨论】:

【参考方案2】:

没有API函数可以做你想做的事,但你可以做以下事情:

window.requestAnimationFrame(function()

    do_before();
    window.requestAnimationFrame(do_after);
);

这确保您的do_after 在第一个动画帧之后被调用,并在它完成执行后触发第二个。

【讨论】:

do_after 在下一次渲染之前执行(与do_before 相同)所以这并不能解决作者的问题

以上是关于动画帧渲染后的javascript运行函数的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 javascript 创建自定义关键帧 css 动画

JS动画 与 CSS3动画 及 回流和重绘

JavaScript之动画2

深入解析 EventLoop 和浏览器渲染帧动画空闲回调的关系

浏览器渲染基本原理:优化渲染性能

[UWP]缓存Lottie动画帧