I may have been exaggerating slightly in that opening paragraph, but you all know you enjoyed it. In any case, the way animation has been done in the past, and is still done by many, is littered with frailties. To understand the flaws, we need to know how animation was done.
setTimeout were the core means of controlling the time between each frame. These two native functions behave the same way except that
setTimeout will run only once, whereas
setInterval will run continuously until
clearInterval is called. You can see a simple example of how they work below:
// Use setInterval to continually update every 20ms until told to stop.
Overall, there’s nothing wrong with this and it has served us well enough throughout the years. There are several issues with these methods though:
- You can’t rely on the number of milliseconds you set to be exact. If your application is very time-sensitive, then you need some special tricks to keep things within an acceptable level of tolerance.
- These methods are explicitly used for animation, so the browser, CPU, and GPU can’t optimize them for animation. For example, a background tab/window utilizing
setIntervalcannot be throttled to use fewer resources because the browser has no way of knowing that they are only being used for animation.
- They don’t synchronize with the browser’s built in rendering frames, so the CPU is used more while trying to redrawing both your animation and the entire screen.
It wasn’t so long ago that Mozilla devised a solution to all of the above problems and they called it requestAnimationFrame. Soon afterward Chrome and Safari picked up the new method. IE will have this soon too. Sadly, they’re each using their vendor prefixes, but a polyfill has been created to assist browsers that don’t have
requestAnimationFrame and to eliminate the need for the prefixes.
Essentially you can just replace
setTimeout directly with
requestAnimationFrame and skip the interval argument and your code will work. The only difference between the two is that instead of waiting a desired number of milliseconds, you will wait until the browser is ready to redraw the screen again. The frequency of redraws is almost always 60 frames per second (16.66ms) and synchronizes with most computer monitors, which greatly optimizes the timing for everything, which saves the computer from doing all the extra work when it’s not ready to redraw a frame. Another upside is that the browser is in control of when an animation frame is ready, so they can throttle the number of frames per second on background tabs to save some CPU cycles and battery life.
I didn’t get much into the details of using
requestAnimationFrame, did I? Well, that’s partially because I like to keep the posts a little more on the short side (which I’m sure you slow readers out there enjoy), but the biggest reason is that I’m planning on doing a video tutorial next week to walk you through some techniques you can use with
requestAnimationFrame. In the meantime, you can waste some time reading the spec, or play with this jsFiddle that shows a little of what can be done with
requestAnimationFrame. Happy Coding!