Using requestAnimationFrame for Web Browser animations instead of setTimeout

HTML5JavaScriptAnimationPerformanceGame Development

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

  1. Browser Optimization: The browser can optimize animations to be smoother by syncing with the display's refresh rate (typically 60Hz).

  2. Battery Efficiency: Animations are paused when the tab is not visible or the window is minimized, saving CPU and battery.

  3. Grouping Visual Changes: The browser can group visual changes together, reducing layout thrashing.

  4. 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)

Continue Reading

Browse All Articles