ArticlesProjectsAbout

Mastering requestAnimationFrame: A Guide for Smooth Animations in JavaScript

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?

  1. 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.

  2. 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.

  3. Automatic Pause for Background Tabs
    When a tab is inactive, requestAnimationFrame halts execution to save resources, unlike setInterval or setTimeout, which continue running in the background.


How Does It Work?

To create an animation using requestAnimationFrame, follow these steps:

  1. Define an Animation Function
    The function will update the properties of the elements you want to animate.

  2. Call requestAnimationFrame
    Use requestAnimationFrame within your animation function to recursively call itself, creating a loop.

  3. 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

  1. Keep Animations Lightweight
    Minimize the workload in your animation function. Complex calculations or DOM manipulations can hinder performance.

  2. Combine with CSS Transitions or Transformations
    Use properties like transform and opacity for smoother animations, as these are GPU-accelerated.

  3. Cancel Animations with cancelAnimationFrame
    Use the ID returned by requestAnimationFrame to cancel an ongoing animation:

    const animationId = requestAnimationFrame(animate); cancelAnimationFrame(animationId);
  4. 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!

Like the article? Share it with others or copy the link!