Using requestAnimationFrame for Web Browser animations instead of setTimeout
Why requestAnimationFrame is superior to setTimeout for HTML5 animations and games
Using requestAnimationFrame for Web Browser animations instead of setTimeout
For almost all the HTML5 games that you come across these days, the game loop works with either setInterval() or setTimeout(). These are basic JavaScript timing functions that work well enough for small games, but when dealing with WebGL-based high-end games, this method ends up consuming a lot of system resources.
The Problem with setTimeout and setInterval
One of the main concerns with these traditional methods is that the browser doesn't have control over setTimeout and setInterval. These functions continue to execute even when:
- The window has been minimized
- The user has switched to a different tab
- The animation is not visible on screen
- The device battery is running low
This leads to unnecessary CPU usage, battery drain on mobile devices, and can negatively impact the overall user experience.
Enter requestAnimationFrame
The requestAnimationFrame
API was specifically designed to solve these problems. It's a browser API that lets you schedule animations in a way that works with the browser's rendering cycle.
// Traditional approach
function animateWithSetTimeout() {
// Update animation state
moveElements();
drawElements();
// Schedule next frame
setTimeout(animateWithSetTimeout, 16); // Roughly 60fps
}
// Modern approach
function animateWithRAF() {
// Update animation state
moveElements();
drawElements();
// Schedule next frame
requestAnimationFrame(animateWithRAF);
}
// Start the animation
requestAnimationFrame(animateWithRAF);
Benefits of requestAnimationFrame
-
Browser Optimization: The browser can optimize animations to be smoother by syncing with the display's refresh rate (typically 60Hz).
-
Battery Efficiency: Animations are paused when the tab is not visible or the window is minimized, saving CPU and battery.
-
Grouping Visual Changes: The browser can group visual changes together, reducing layout thrashing.
-
Automatic Throttling: In low-power situations, the browser can throttle animations appropriately.
Performance Comparison
When testing animations using both methods, requestAnimationFrame consistently provides:
- Smoother animations with fewer frame drops
- Lower CPU usage
- Better battery life on mobile devices
- More consistent frame rates
Cross-Browser Implementation
Early browser support for requestAnimationFrame was inconsistent. Here's a cross-browser implementation with fallbacks:
// Cross-browser requestAnimationFrame
window.requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
// Usage
function animate() {
// Animation code here
requestAnimFrame(animate);
}
animate();
When to Use Each Method
You should use requestAnimationFrame for:
- Visual animations
- Games
- Anything that updates the DOM or canvas visually
You should use setTimeout/setInterval for:
- Non-visual operations
- Polling operations
- When you need a guaranteed time interval
Conclusion
As HTML5 games and animations become more complex, using requestAnimationFrame instead of setTimeout/setInterval becomes increasingly important. It provides smoother animations, better performance, and more efficient resource usage.
For most modern web browsers, requestAnimationFrame is now well-supported, making it the preferred choice for animation loops in HTML5 games and visual effects.
Note: This article was migrated from the original A thousand nodes blog (2011)