requestAnimationFrame called right before the end of the frame?
Asked Answered
S

1

5

I've been experimenting with jank-free rendering of complex scenes on HTML5 canvas. The idea is to split rendering into multiple batches with each batch taking a maximum of, say 12 ms, so that the concurrently running animations (very cheap to execute) are not interrupted.

Conceptually, batch-rendering is implemented like this:

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
    } 
  }); 
}

The complete code is in this JSFiddle: https://jsfiddle.net/fkfnjrc2/5/. The code does the following things:

  • On each frame, modify the CSS transform property of the canvas (which is an example of the concurrently-running fast-to-execute animation).
  • Once in a while, initiate re-rendering of the canvas in the batched fashion as shown above.

Unfortunately, I'm seeing horrible janks exactly at the times when canvas contents is re-rendered. What I don't seem to be able to explain is what the Chrome Developer Tools timeline looks like:

Janks in the Chrome Developer Tools timeline view

The dropped frames seem to be caused by the fact that the requestAnimationFrame is not called right at the start of the frame, but towards the end of the ideal 16ms period. If the callback started right after the previous frame completed rendering, the code would most likely complete in time.

Rendering to an off-screen canvas (https://jsfiddle.net/fkfnjrc2/6/) and then copying the complete image to the screen canvas helps a little, but the janks are still there with exactly the same characteristics (delayed execution of rAF callback).

What is wrong with that code? Or maybe something's wrong with my browser / machine? I'm seeing the same behaviour on Chrome (49.0.2623.112) on Windows 10 and Mac OS.

Slum answered 20/4, 2016 at 12:50 Comment(0)
S
1

The issues seem to be caused by Chrome's specific requestAnimationFrame callback scheduling. I've filed a bug to track this, it contains some simpler reproduction code examples.

Slum answered 8/5, 2016 at 19:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.