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,requestAnimationFramecalls your animation at 60 fps. If the refresh rate drops, the API adjusts accordingly. -
Automatic Pause for Background Tabs
When a tab is inactive,requestAnimationFramehalts execution to save resources, unlikesetIntervalorsetTimeout, 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
UserequestAnimationFramewithin 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 liketransformandopacityfor smoother animations, as these are GPU-accelerated. -
Cancel Animations with
cancelAnimationFrame
Use the ID returned byrequestAnimationFrameto cancel an ongoing animation:const animationId = requestAnimationFrame(animate); cancelAnimationFrame(animationId); -
Use
performance.nowfor 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!