Lesson 15 - JS requestAnimationFrame - For better drawing
The previous lesson, Timers and animations in JavaScript, was about animations. Together with HTML5, a new JavaScript API - requestAnimationFrame has been added. It's a technology that allows us to render animations in the browser more fluently and with higher performance. We'll introduce the technology in today's JavaScript tutorial.
If you ever tried to program a simple browser game, your main loop might looked like this.
setInterval(function() { update(); render(); }, 1000 / FPS);
Our previous animations looked very similar, we only combined updating and rendering into a single function. An alternative rendering loop may also look like this:
function loop() { setTimeout(loop, 1000 / FPS); update(); render(); } loop();
The code works, we can even limit FPS. So what's wrong with it?
Wasting computing power
The problem with the code above is that the browser invokes it even if the user is not looking at the page (they switched to another tab or minimized the browser). The Google Chrome browser handles these situations by restricting such loops to only 1 FPS. But this is only its voluntary behavior, and other browsers might not do it. We may experience unnecessary performance drops and discharges on mobile devices.
requestAnimationFrame solves it!
Using the requestAnimationFrame()
function instead of
setTimeout()
, our code will look very similarly.
function loop() { requestAnimationFrame(loop); update(); render(); } loop();
Mozilla invented this feature and the WebKit team later took over and improved it. We can use it to draw CSS, DOM elements, WebGL, or on canvas.
Advantages
requestAnimationFrame()
will ensure that all of our animations
are rendered at once, with higher performance and lower battery consumption.
If you switch to another tab in your browser or you minimize the browser, the rendering will stop to save power and will continue as soon as the page is visible again.
You may have also noticed that using requestAnimationFrame()
we
have never set the number of FPS. By default, the function uses 60 FPS, but it
depends on the browser implementation. However, it should not be too different
and it depends on the PC's performance rather than on the browser creator's
decision. Also, the support across browsers is quite good.
Demo
At the end, we'll show a simple application in which a square moves on a
canvas. We'll implement it using both setInterval()
and
requestAnimationFrame()
. We won't clear the canvas this time on
purpose, so we'll see the square's trace.
The solution using setInterval()
window.onload = function() { let canvas = document.querySelector("#canvas"); let context = canvas.getContext("2d"); let square = { "x": 25, "y": 25, "dirX": -1, "dirY": 1, "speed": 2, "sizeX": 50, "sizeY": 50, "color": "red" }; function loop() { update(); render(); } setInterval(function() { update(); render(); }, 1000 / 60); loop(); function update() { if (square.x + square.sizeX + square.speed * square.dirX > canvas.width) square.dirX = -1; if (square.x + square.speed * square.dirX < 0) square.dirX = 1; if (square.y + square.sizeY + square.speed * square.dirY > canvas.height) square.dirY = -1; if (square.y + square.speed * square.dirY < 0) square.dirY = 1; changeColor(); square.x += square.speed * square.dirX; square.y += square.speed * square.dirY; } function render() { context.fillStyle = square.color; context.fillRect(square.x, square.y, square.sizeX, square.sizeY); } function changeColor() { colors = ['green', 'blue', 'red', 'yellow']; square.color = colors[Math.floor(Math.random() * colors.length)]; } }
The result:
The solution using requestAnimationFrame()
window.onload = function() { let canvas = document.querySelector("#canvas"); let context = canvas.getContext("2d"); let square = { "x": 25, "y": 25, "dirX": -1, "dirY": 1, "speed": 2, "sizeX": 50, "sizeY": 50, "color": "red" }; function loop() { update(); render(); requestAnimationFrame(loop); } loop(); function update() { if (square.x + square.sizeX + square.speed * square.dirX > canvas.width) square.dirX = -1; if (square.x + square.speed * square.dirX < 0) square.dirX = 1; if (square.y + square.sizeY + square.speed * square.dirY > canvas.height) square.dirY = -1; if (square.y + square.speed * square.dirY < 0) square.dirY = 1; changeColor(); square.x += square.speed * square.dirX; square.y += square.speed * square.dirY; } function render() { context.fillStyle = square.color; context.fillRect(square.x, square.y, square.sizeX, square.sizeY); } function changeColor() { colors = ['green', 'blue', 'red', 'yellow']; square.color = colors[Math.floor(Math.random() * colors.length)]; } }
The result:
I hope the lesson has been useful for you and you will be using
requestAnimationFrame()
in your animations
Download
Downloaded 0x (3.33 kB)
Application includes source codes in language JavaScript
Comments
No one has commented yet - be the first!