【问题标题】:javascript run function after animation frame renders动画帧渲染后的javascript运行函数
【发布时间】: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() 在屏幕完成绘制后运行?

提前致谢

【问题讨论】:

    标签: javascript html css google-chrome animation


    【解决方案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 相同)所以这并不能解决作者的问题