Reputation: 173
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:
Is there a way to make do_after() run after the screen has finished drawing itself?
Thanks in advance
Upvotes: 5
Views: 3033
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
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