/

A Comprehensive Guide to Using requestAnimationFrame()

A Comprehensive Guide to Using requestAnimationFrame()

Learn how to use the requestAnimationFrame() API for performing animations and scheduling events in a predictable manner.

The requestAnimationFrame() API is a relatively new addition to web browsers and provides a more predictable way to hook into the browser’s render cycle. It is supported by all modern browsers, including IE 10 and above.

Although not specific to animations, requestAnimationFrame() is commonly used for animating elements on a webpage.

In the past, animations were typically implemented using setTimeout() or setInterval(). With this approach, you would perform a small portion of the animation and then call setTimeout() or setInterval() to repeat the code after a few milliseconds.

Example using setTimeout():

1
2
3
4
5
6
const performAnimation = () => {
// ...
setTimeout(performAnimation, 1000 / 60);
};

setTimeout(performAnimation, 1000 / 60);

Example using setInterval():

1
2
3
4
5
const performAnimation = () => {
// ...
};

setInterval(performAnimation, 1000 / 60);

To stop an animation, you would need to keep track of the timeout or interval reference and clear it.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
let timer;

const performAnimation = () => {
// ...
timer = setTimeout(performAnimation, 1000 / 60);
};

timer = setTimeout(performAnimation, 1000 / 60);

// ...

clearTimeout(timer);

It’s important to note that the interval of 1000/60 (approximately 16.6ms) between the performAnimation() calls is determined by the monitor’s refresh rate of 60Hz. This ensures that each frame is displayed within the available time frame.

However, a drawback of this approach is that if the browser is busy with other operations, the setTimeout calls may not make it in time for the repaint, resulting in a delayed animation or skipped frames. This can lead to a clunky animation experience for users.

To address this issue, requestAnimationFrame() provides a more efficient way to perform animations. Although the code looks similar to that of setTimeout() or setInterval(), requestAnimationFrame() works in a completely different way.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
let request;

const performAnimation = () => {
request = requestAnimationFrame(performAnimation);
// animate something
};

requestAnimationFrame(performAnimation);

// ...

cancelAnimationFrame(request); // stop the animation

Unlike setTimeout() or setInterval(), requestAnimationFrame() intelligently optimizes resource consumption by pausing animations when the current window or tab is not visible. This not only enhances performance but also results in smoother animations. Browsers have also implemented throttling for setTimeout() and setInterval() to achieve similar benefits.

Here is a comparison of the timeline using setTimeout/setInterval and requestAnimationFrame():

Perfect timeline with setTimeout/setInterval:

Perfect timeline

Choppy timeline with a higher frequency using setTimeout/setInterval:

Too frequent timeline

Missed frame due to delay in the event loop:

Missed frame

Delayed animation step and subsequent delay in rendering and painting:

Delay in the timeline

Predictable timeline using requestAnimationFrame():

requestAnimationFrame timeline

Using requestAnimationFrame(), all animation code runs before rendering and painting events, allowing more control over the animation process.

For more information, watch this informative video by Jake Archibald on requestAnimationFrame.

tags: [“animation”, “requestAnimationFrame”, “setTimeout”, “setInterval”, “optimization”]