requestAnimationFrame在帧结束前调用了吗?

时间:2016-04-20 12:50:02

标签: javascript performance animation canvas requestanimationframe

我一直在尝试在HTML5画布上进行复杂场景的无抖动渲染。我们的想法是将渲染分成多个批次,每个批次最多占用12毫秒,这样就不会中断同时运行的动画(非常便宜的执行)。

从概念上讲,批量渲染的实现方式如下:

function draw(ctx) {
  var deadline = window.performance.now() + 12; // inaccurate, but enough for the example
  var i = 0;
  requestAnimationFrame(function drawWithDeadline() {
    for (; i < itemsToRender.length; i++) {
      if (window.performance.now() >= deadline) {
        requestAnimationFrame(drawWithDeadline);
        return; 
      }

      var item = itemsToDraw[i];
      // Draw item
    } 
  }); 
}

完整的代码在这个JSFiddle中:https://jsfiddle.net/fkfnjrc2/5/。该代码执行以下操作:

  • 在每个帧上,修改画布的CSS转换属性(这是同时运行的快速执行动画的示例)。
  • 偶尔会以批量方式启动画布的重新渲染,如上所示。

不幸的是,我正在重新渲染画布内容的时候看到可怕的janks。我似乎无法解释的是Chrome开发者工具时间表的样子:

Janks in the Chrome Developer Tools timeline view

丢帧似乎是由于requestAnimationFrame未在帧开始时调用,而是在理想的16ms周期结束时调用。如果在前一帧完成渲染之后立即开始回调,则代码很可能会及时完成。

渲染到离屏画布(https://jsfiddle.net/fkfnjrc2/6/),然后将完整的图像复制到屏幕画布有一点帮助,但是jank仍然存在完全相同的特征(延迟执行rAF回调)。

该代码有什么问题?或者我的浏览器/机器可能有问题?我在Windows 10和Mac OS上的Chrome(49.0.2623.112)上看到了相同的行为。

1 个答案:

答案 0 :(得分:1)

这些问题似乎是由Chrome的特定requestAnimationFrame回调计划引起的。我已经提交了一个bug来跟踪它,它包含一些更简单的再现代码示例。