If you're building games with JavaScript, requestAnimationFrame
(rAF) is the most important function you need to know. It’s the secret sauce behind smooth, efficient animations—and using it correctly can make or break your game’s performance.
In this post, we’ll explore:
✔ What requestAnimationFrame
does
✔ Why it’s better than setInterval
or setTimeout
✔ How to use it in your game loop
✔ Common mistakes to avoid
1. What is requestAnimationFrame
?
requestAnimationFrame
is a browser API designed specifically for smooth animations and games. Instead of running at arbitrary intervals (like setInterval
), it syncs with your monitor’s refresh rate (usually 60Hz, meaning 60 FPS).
Basic Syntax
function gameLoop(timestamp) {
// Game logic & rendering here
requestAnimationFrame(gameLoop); // Schedule next frame
}
// Start the game loop
requestAnimationFrame(gameLoop);
2. Why Use rAF Instead of setInterval
or setTimeout
?
Feature | requestAnimationFrame |
setInterval /setTimeout |
---|---|---|
Framerate | Matches display refresh rate (smooth) | Fixed interval (can stutter) |
Battery Efficiency | Pauses in background tabs | Keeps running, wasting CPU |
Jank Prevention | Avoids frame drops by syncing with GPU | Can cause missed frames |
Automatic Delta Time | Provides a high-res timestamp | Requires manual timing |
Key Advantages of rAF:
✅ Smoother gameplay – No tearing or skipped frames
✅ More efficient – Doesn’t run when the tab is hidden
✅ Built for animations – Optimized by browsers
3. How to Use rAF in a Game Loop
A proper game loop should:
-
Track time between frames (delta time)
-
Update game logic (physics, input, AI)
-
Render the frame
let lastTime = 0;
function gameLoop(timestamp) {
// Calculate delta time (seconds since last frame)
const deltaTime = (timestamp - lastTime) / 1000;
lastTime = timestamp;
// Update game state (movement, collisions, etc.)
update(deltaTime);
// Draw everything
render();
// Repeat
requestAnimationFrame(gameLoop);
}
// Start the game
requestAnimationFrame(gameLoop);
Why Delta Time Matters
Without it, your game would run faster on high-refresh-rate monitors and slower on old devices. Delta time ensures consistent speed across all hardware.
4. Common Mistakes (And How to Fix Them)
❌ Mistake 1: Not Using Delta Time
Bad:
player.x += 5; // Speed depends on framerate
Good:
player.x += 5 * deltaTime; // Speed is consistent
❌ Mistake 2: Running Logic When Tab is Hidden
Fix:
if (!document.hidden) {
update(deltaTime); // Only run when visible
}
❌ Mistake 3: Forgetting to Cancel rAF
If your game has screens (menu, pause), always cancel the loop:
let animationId;
function startGame() {
animationId = requestAnimationFrame(gameLoop);
}
function pauseGame() {
cancelAnimationFrame(animationId);
}
5. When Should You Not Use rAF?
While requestAnimationFrame
is ideal for rendering, avoid it for:
-
Non-visual logic (use Web Workers instead)
-
Network requests (use
setTimeout
or Promises) -
Heavy computations (can block rendering)
Conclusion: Why rAF Wins
If you want buttery-smooth gameplay, requestAnimationFrame
is the only correct choice. It’s:
🔥 Optimized for animations
🔋 Battery-friendly
⏱️ Precision-timed
Try it in your next game! For a complete example, check out:
Basic Game Scaffold on GitHub
Bonus: Quick Comparison
requestAnimationFrame |
setInterval |
---|---|
✅ Syncs with display | ❌ Fixed interval |
✅ Efficient | ❌ Wastes CPU |
✅ Smooth animations | ❌ Can stutter |