pedrumj
pedrumj

Reputation: 173

javascript run function after animation frame renders

Based on what I understand you need 60fps on your animations to make the animations appear smooth. Basically what I'm trying to do is to do the heavy calculations at the start of the frame so by the time the rendering is actually going to happen there won't be much work left to do.

I understand you can use window.requestAnimationFrame to run a function right before the screen is redrawn. But that will cause a jerking effect if the function takes a long time. Is there a way to run a function right after the screen has done a repaint?

I tried something like this but its miss and hit:

window.requestAnimationFrame(do_before);

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

do_after(){
    //code to execute after animation frame
}

As you can see in the picture below the do_after code is still executing in the same frame and because of this I sometimes get long frames:

Link to image

Is there a way to make do_after() run after the screen has finished drawing itself?

Thanks in advance

Upvotes: 5

Views: 3033

Answers (2)

Finesse
Finesse

Reputation: 10801

Actually, the code from you question is right. setTimeout(do_after) is enough in Chrome and Safari (I haven't tested in other browsers). It makes the browser execute the function when the browser is free of other tasks.

If you want to delay the execution from inside a requestAnimationFrame callback, just call setTimeout(do_after) and the callback will be executed right after the frame flush:

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

If you want to delay the execution from another place (e.g. a click handler or an AJAX response handler), call requestAnimationFrame first and then setTimeout:

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

Unfortunately I haven't found a universal way to execute a callback right at the start of the next frame because there is no straightforward way to know if a code is executed inside a requestAnimationFrame handler. You may use a trick to solve it

If you need to execute a callback right after any frame flush, use the second approach (requestAnimationFrame + setTimeout). It may lead to idling a whole animation frame before running the callback.

Upvotes: 3

Anonymous
Anonymous

Reputation: 11

There is no API function to do what you want, but you can do the following:

window.requestAnimationFrame(function()
{
    do_before();
    window.requestAnimationFrame(do_after);
});

This makes sure your do_after is called after the first animation frame, and will trigger a second one after it's done executing.

Upvotes: 1

Related Questions