Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
How to control fps with requestAnimationFrame?
The fps (frames per second) is crucial for animations and games, determining how many times the screen updates per second. JavaScript's requestAnimationFrame() typically runs at 60fps, but we can control this rate using different approaches.
For example, a video is a continuous sequence of images shown at short intervals. Higher fps provides smoother animations, while lower fps can create choppy effects. Understanding fps control helps optimize performance and create desired visual effects.
Using setTimeout() with requestAnimationFrame
The setTimeout() function can delay requestAnimationFrame() calls to control fps. We calculate the interval as 1000/fps milliseconds.
Syntax
setTimeout(() => {
requestAnimationFrame(animate);
}, interval);
Example: Basic FPS Control
<html>
<body>
<h3>Using <i>setTimeout()</i> to control fps with requestAnimationFrame</h3>
<div id="output"></div>
<script>
let output = document.getElementById("output");
let totalFrames = 0;
let current, consumedTime;
// Set fps to 3 (slow animation)
let fps = 3;
let intervalOffps = 1000 / fps;
let startTime = Date.now();
animate();
function animate() {
setTimeout(() => {
requestAnimationFrame(animate);
current = Date.now();
let elapsed = current - startTime;
// Calculate current fps
let currentFps = Math.round((1000 / (elapsed / ++totalFrames)) * 100) / 100;
output.innerHTML = "Elapsed time: " + Math.round((elapsed / 1000) * 100) / 100 +
" seconds @ " + currentFps + " fps";
}, intervalOffps);
}
</script>
</body>
</html>
Using Time Comparison Method
This approach checks if enough time has passed since the last frame before rendering. We only update when the time difference exceeds our target interval.
Syntax
let consumedTime = current - lastFrameTime;
if (consumedTime > intervalOffps) {
// Render frame
}
Example: Time-Based FPS Control
<html>
<body>
<h3>Using <i>Date() object</i> to control fps with requestAnimationFrame</h3>
<div id="output"></div>
<script>
let output = document.getElementById("output");
let totalFrames = 0;
let current, consumedTime;
// Set fps to 30
let fps = 30;
let intervalOffps = 1000 / fps;
let lastFrameTime = Date.now();
let startTime = lastFrameTime;
animate();
function animate() {
requestAnimationFrame(animate);
current = Date.now();
consumedTime = current - lastFrameTime;
// Only render if enough time has passed
if (consumedTime > intervalOffps) {
lastFrameTime = current - (consumedTime % intervalOffps);
let elapsed = current - startTime;
let currentFps = Math.round((1000 / (elapsed / ++totalFrames)) * 100) / 100;
output.innerHTML = "Elapsed time: " + Math.round((elapsed / 1000) * 100) / 100 +
" seconds @ " + currentFps + " fps";
}
}
</script>
</body>
</html>
Example: Interactive Canvas Animation
This example demonstrates fps control with a visual canvas animation. Use the range slider to adjust fps and observe the animation speed difference.
<html>
<body>
<h3>Interactive FPS Control with Canvas Animation</h3>
<label>FPS: </label>
<input type="range" min="1" max="60" value="10" id="fps">
<button onclick="startAnimation()">Start Animation</button>
<button onclick="stopAnimation()">Stop</button>
<br><br>
<canvas id="canvas" width="300" height="300" style="border:1px solid #000;"></canvas>
<script>
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
let animation;
let intervalOffps, current, lastFrameTime, elapsed;
let angle = 0;
let isAnimating = false;
function drawShape() {
// Clear canvas
context.clearRect(0, 0, canvas.width, canvas.height);
context.save();
context.translate(150, 150);
context.rotate(Math.PI / 180 * (angle += 5));
// Draw rotating rectangle
context.fillStyle = "#007acc";
context.fillRect(-25, -25, 50, 50);
context.restore();
// Reset angle after full rotation
if (angle >= 360) angle = 0;
}
function animate() {
if (!isAnimating) return;
animation = requestAnimationFrame(animate);
current = Date.now();
elapsed = current - lastFrameTime;
// Only draw if enough time has passed
if (elapsed > intervalOffps) {
lastFrameTime = current - (elapsed % intervalOffps);
drawShape();
}
}
function startAnimation() {
if (isAnimating) stopAnimation();
let fpsInput = document.getElementById("fps");
let fps = fpsInput.value;
intervalOffps = 1000 / fps;
lastFrameTime = Date.now();
isAnimating = true;
animate();
}
function stopAnimation() {
isAnimating = false;
if (animation) {
cancelAnimationFrame(animation);
}
}
</script>
</body>
</html>
Comparison of Methods
| Method | Precision | Performance | Use Case |
|---|---|---|---|
| setTimeout() | Good | Lower | Simple animations |
| Time Comparison | High | Better | Smooth animations, games |
Conclusion
Both methods effectively control fps with requestAnimationFrame(). The time comparison method offers better performance and precision, making it ideal for games and complex animations where smooth frame control is crucial.
