Animations are a cornerstone of modern web experiences, and as a developer, you’ve likely faced the challenge of creating smooth, performant animations. Enter requestAnimationFrame
, a browser API that has revolutionized how we handle animations in JavaScript.
In this post, we'll dive into what requestAnimationFrame
is, how it works, and why it's your go-to solution for creating buttery-smooth animations.
What is requestAnimationFrame
?
requestAnimationFrame
is a method provided by browsers to schedule animation updates. Unlike setInterval
or setTimeout
, it synchronizes your animations with the display refresh rate, usually 60 frames per second (fps) on most monitors. This synchronization ensures smoother animations and better performance.
Syntax:
window.requestAnimationFrame(callback);
callback
: A function that will be called to update the animation.
Why Use requestAnimationFrame
?
-
Performance Optimizations
The browser optimizes animations by ensuring updates occur only when the screen is ready to repaint. This reduces unnecessary calculations and improves battery life on devices. -
Consistency with Frame Rates
It adapts to the refresh rate of the display. If the display runs at 60 fps,requestAnimationFrame
calls your animation at 60 fps. If the refresh rate drops, the API adjusts accordingly. -
Automatic Pause for Background Tabs
When a tab is inactive,requestAnimationFrame
halts execution to save resources, unlikesetInterval
orsetTimeout
, which continue running in the background.
How Does It Work?
To create an animation using requestAnimationFrame
, follow these steps:
-
Define an Animation Function
The function will update the properties of the elements you want to animate. -
Call
requestAnimationFrame
UserequestAnimationFrame
within your animation function to recursively call itself, creating a loop. -
Stop the Animation
Use a condition to stop the animation when it completes.
Example: A Simple Ball Animation
Here’s how you can animate a ball moving across the screen using requestAnimationFrame
:
// Initial setup const ball = document.getElementById("ball"); let position = 0; const maxPosition = window.innerWidth - ball.offsetWidth; // Animation function function animate() { position += 5; // Move the ball to the right ball.style.transform = `translateX(${position}px)`; // Stop animation when it reaches the edge if (position < maxPosition) { requestAnimationFrame(animate); } } // Start animation requestAnimationFrame(animate);
HTML:
<div id="ball" style="width: 50px; height: 50px; background: red; border-radius: 50%; position: absolute;" ></div>
Tips for Effective Use
-
Keep Animations Lightweight
Minimize the workload in your animation function. Complex calculations or DOM manipulations can hinder performance. -
Combine with CSS Transitions or Transformations
Use properties liketransform
andopacity
for smoother animations, as these are GPU-accelerated. -
Cancel Animations with
cancelAnimationFrame
Use the ID returned byrequestAnimationFrame
to cancel an ongoing animation:const animationId = requestAnimationFrame(animate); cancelAnimationFrame(animationId);
-
Use
performance.now
for Timing
Track elapsed time accurately for complex animations:let start = null; function step(timestamp) { if (!start) start = timestamp; const progress = timestamp - start; ball.style.transform = `translateX(${Math.min(progress / 5, maxPosition)}px)`; if (progress < maxPosition * 5) { requestAnimationFrame(step); } } requestAnimationFrame(step);
When Not to Use requestAnimationFrame
While requestAnimationFrame
is excellent for most animations, there are cases where CSS animations or the Web Animations API may be a better fit, particularly for simple, declarative animations.
Conclusion
requestAnimationFrame
is a powerful tool for crafting smooth, efficient animations in JavaScript. By aligning updates with the browser's rendering cycles, it ensures optimal performance and an enhanced user experience.
So the next time you need an animation, ditch setInterval
and embrace requestAnimationFrame
—your users (and their devices) will thank you!