帧末期之前调用requestAnimationFrame?

5

我一直在尝试在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变换属性(这是一个同时运行的快速执行动画示例)。
  • 偶尔,按照上面所示的批处理方式启动重新渲染画布。
不幸的是,当画布内容重新渲染时,我看到了可怕的卡顿。我似乎无法解释Chrome开发者工具时间轴的情况: Janks in the Chrome Developer Tools timeline view 丢失的帧似乎是由于requestAnimationFrame没有在帧开始时立即调用,而是在理想的16ms周期朝着结束方向调用。如果回调函数在上一帧完成渲染后立即开始,则代码很可能会及时完成。
将图像渲染到离屏画布中(https://jsfiddle.net/fkfnjrc2/6/),然后将完整的图像复制到屏幕画布中可以稍微帮助一下,但是仍然存在与之前完全相同的卡顿(rAF回调延迟执行)。
那段代码有什么问题?或者我的浏览器/机器有问题吗?我在Windows 10和Mac OS上的Chrome(49.0.2623.112)上看到了相同的行为。
1个回答

1
问题似乎是由Chrome特定的requestAnimationFrame回调安排引起的。我已经提交了一个错误来跟踪此问题,其中包含一些更简单的复制代码示例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接