How to control fps with requestAnimationFrame?

02 Jun, 2020
Introduction:It is important to control the frames per second limit, especially, when developing games where the animated objects should not exceed particular frames per second limit. The requestAnimationFrame() is used for simply repainting the screen — it is not a timer or a loop function.
requestAnimationFrame(callback):Used to update or repaint the screen using the callback function specified.
Whenever a function call is made to requestAnimationFrame() the screen/frame is repainted according to the update code written by the developer, which makes it a suitable option for controlling the frame rate. There are two ways of controlling the fps with requestAnimationFrame(). These are discussed as follows.
Using `setTimeout` Function:This is a quick and easy approach to controlling the fps. The setTimeout() function has the following declaration:setTimeout(function, milliseconds) :Can be used to execute a function after waiting for the specified number of seconds.The code to control fps using setTimeout() is given below, the requestAnimationFrame() is passed as a function to setTimeout() for regularly updating the screen at the specified fps.<h1>Controlling requestAnimationFrame to a FPS</h1><h2>Testing approach 1:          Results should be approximately 5 fps</h2><h3 id="results">Results:</h3><canvas id="canvas" width="300" height="300"></canvas>  <script>    var frameCount = 0;    var $results = $("#results");    var fps, fpsInterval, startTime, now, then, elapsed;      startAnimating(5);      function startAnimating(fps) {        fpsInterval = 1000 / fps;        then = Date.now();        startTime = then;        console.log(startTime);        animate();    }      function animate() {        setTimeout(function () {      // requestAnimationFrame() is called       // with animate() callback      // to update content at specified fps            requestAnimationFrame(animate);              // ... Code for Animating the Objects ...            now = Date.now();            var sinceStart = now - startTime;            var currentFps =  Math.round((1000 / (sinceStart / ++frameCount)) * 100) / 100;   $results.text("Elapsed time= "          + Math.round((sinceStart / 1000) * 100) / 100 +         " secs @ " + currentFps + " fps.");        }, fpsInterval);    }</script>Output:The two images show the fps fluctuating around 5 fps, as assumed by the above code.
setTimeout(function, milliseconds) :Can be used to execute a function after waiting for the specified number of seconds.
The code to control fps using setTimeout() is given below, the requestAnimationFrame() is passed as a function to setTimeout() for regularly updating the screen at the specified fps.
<h1>Controlling requestAnimationFrame to a FPS</h1><h2>Testing approach 1:          Results should be approximately 5 fps</h2><h3 id="results">Results:</h3><canvas id="canvas" width="300" height="300"></canvas>  <script>    var frameCount = 0;    var $results = $("#results");    var fps, fpsInterval, startTime, now, then, elapsed;      startAnimating(5);      function startAnimating(fps) {        fpsInterval = 1000 / fps;        then = Date.now();        startTime = then;        console.log(startTime);        animate();    }      function animate() {        setTimeout(function () {      // requestAnimationFrame() is called       // with animate() callback      // to update content at specified fps            requestAnimationFrame(animate);              // ... Code for Animating the Objects ...            now = Date.now();            var sinceStart = now - startTime;            var currentFps =  Math.round((1000 / (sinceStart / ++frameCount)) * 100) / 100;   $results.text("Elapsed time= "          + Math.round((sinceStart / 1000) * 100) / 100 +         " secs @ " + currentFps + " fps.");        }, fpsInterval);    }</script>
Output:The two images show the fps fluctuating around 5 fps, as assumed by the above code.
FPS is 4.9, after 5.31 seconds have elapsed:
FPS is 4.91, after 18.34 seconds have elapsed:
The above code is simply, calling the setTimeout() function at the interval rate specified by the fps. Each time setTimeout() is called, the requestAnimationFrame() is executed and the screen is repainted or updated. All this occurs at the fps specified, as determined by the developer.
A More Optimized Approach:Most browsers cannot optimize the setTimeout() function, so to optimize the process of controlling fps simple calculation can be used. This can be easily done by keeping track of time when the frame was updated last. If the change in time (current time — previous time) exceeds the update interval, then update the frame/screen.To do so, keep track of the current_time and the previous_time. Each time we get:current_time - previous_time > update_interval 
the frame is updated and repainted onto the screen. The code for this is as follows:<h1>Controlling requestAnimationFrame to a FPS</h1><h2>This test: Results should be approximately 5 fps</h2><h2 id="results">Results:</h2><canvas id="canvas" width="300" height="300"></canvas>  <script>    var frameCount = 0;    var $results = $("#results");    var fps, fpsInterval, startTime, now, then, elapsed;      startAnimating(5);      function startAnimating(fps) {        fpsInterval = 1000 / fps;        then = Date.now();        startTime = then;        console.log(startTime);        animate();    }      function animate() {        // request another frame          requestAnimationFrame(animate);          // calc elapsed time since the last loop          now = Date.now();        elapsed = now - then;          // if enough time has elapsed, draw the next frame          if (elapsed > fpsInterval) {            then = now - (elapsed % fpsInterval);          // draw animating objects here...          // below code is used for testing, whether       // the frame is animating at the specified fps              var sinceStart = now - startTime;            var currentFps = Math.round((1000 / (sinceStart / ++frameCount)) * 100) / 100;            $results.text("Elapsed time= "              + Math.round((sinceStart / 1000) * 100) / 100              + " secs @ " + currentFps + " fps.");        }    }</script>Output:The two images show the fps fluctuating around 5 fps, as assumed by the above code.
To do so, keep track of the current_time and the previous_time. Each time we get:
current_time - previous_time > update_interval 

the frame is updated and repainted onto the screen. The code for this is as follows:
<h1>Controlling requestAnimationFrame to a FPS</h1><h2>This test: Results should be approximately 5 fps</h2><h2 id="results">Results:</h2><canvas id="canvas" width="300" height="300"></canvas>  <script>    var frameCount = 0;    var $results = $("#results");    var fps, fpsInterval, startTime, now, then, elapsed;      startAnimating(5);      function startAnimating(fps) {        fpsInterval = 1000 / fps;        then = Date.now();        startTime = then;        console.log(startTime);        animate();    }      function animate() {        // request another frame          requestAnimationFrame(animate);          // calc elapsed time since the last loop          now = Date.now();        elapsed = now - then;          // if enough time has elapsed, draw the next frame          if (elapsed > fpsInterval) {            then = now - (elapsed % fpsInterval);          // draw animating objects here...          // below code is used for testing, whether       // the frame is animating at the specified fps              var sinceStart = now - startTime;            var currentFps = Math.round((1000 / (sinceStart / ++frameCount)) * 100) / 100;            $results.text("Elapsed time= "              + Math.round((sinceStart / 1000) * 100) / 100              + " secs @ " + currentFps + " fps.");        }    }</script>
Output:The two images show the fps fluctuating around 5 fps, as assumed by the above code.
FPS is 4.99, after 8.61seconds have elapsed:
FPS is 5.00, after 9.21 seconds have elapsed:
In the above code, two variable current_time and previous_time are used to keep track of the time elapsed since the last update. Whenever the condition is satisfied (change in time is greater than interval time), the frame is updated to animate the objects.
JavaScript-Misc
Picked
JavaScript
Web Technologies
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Difference between var, let and const keywords in JavaScript
Remove elements from a JavaScript Array
Difference Between PUT and PATCH Request
Roadmap to Learn JavaScript For Beginners
JavaScript | Promises
Top 10 Projects For Beginners To Practice HTML and CSS Skills
Installation of Node.js on Linux
Difference between var, let and const keywords in JavaScript
How to insert spaces/tabs in text using HTML/CSS?
How to fetch data from an API in ReactJS ?