Post navigation

Efficient Animations with requestAnimationFrame

If you are using animations in your web apps you’ll want to make sure that they run smoothly. The easiest way of doing this is to use requestAnimationFrame (sometimes referred to as rAF), a method that makes creating smooth animations effortless.

Using the requestAnimationFrame method allows the browser to handle some of the complicated animation tasks for you, such as managing the frame rate.

Developers have previously used setTimeout and setInterval to create animations. The problem here is that in order for the animations to be smooth the browser often has to paint frames quicker than the screen can display then (most computer screens have a refresh rate of 60 frames per second or FPS). This results in unnecessary computation. Another problem with using setInterval or setTimeout is that the animations will continue to run even if the page is not visible to the user.

Why use requestAnimationFrame?

So why is requestAnimationFrame so great? Lets take a look at some of the things that make requestAnimationFrame superior to using setInterval or setTimeout.

Browser Optimizations

Using requestAnimationFrame gives the browser the ability to optimize your animations to make them smoother and more resource efficient. I won’t go into too much detail on exactly how the browser makes these optimizations, just know that it eliminates the possibility of unnecessary draws and can bunch together multiple animations into a single reflow and repaint cycle.

Animations Only Run When Visible

When using requestAnimationFrame your animations will only run when the tab (or window) is visible to the user. This means less CPU, GPU and memory usage – which brings us on to our final point.

Battery Friendly

The optimizations mentioned in the previous two points all help to reduce the amount of ‘stuff’ that a device has to do to create your animations and therefore helps to conserve battery power. This is especially important for mobile devices that typically have a relatively short battery life.

Using requestAnimationFrame

The requestAnimationFrame method should be passed a callback function that is responsible for drawing a single frame of your animation. In order to create a full animation you will need to make this callback recursive.

A high resolution timestamp (DOMHighResTimeStamp) is passed to the callback function. You won’t always need to use this but it can come in handy for some animations.

The example below shows how to set up a recursive function that uses requestAnimationFrame.

It’s worth noting that you only have 16.67ms to render each frame. This isn’t a great deal of time so you should be careful about what you decide to execute inside the callback function. If your frame takes longer than 16.67ms to render, the animation may not appear as smooth.

The requestAnimationFrame method will return a requestID that can be used for cancelling the scheduled animation frame.

var requestID = requestAnimationFrame(animate);

Cancelling Animation Frames

To cancel a scheduled animation frame you can use the cancelAnimationFrame method. This method should be passed the requestID for the frame you wish to cancel.

cancelAnimationFrame(requestID);

You’ll see how to keep track of the current requestID later.

Polyfill

There’s a great polyfill for requestAnimationFrame that was developed by Erik Möller of Opera (and later worked on by Paul Irish and Tino Zijdel).

In this markup you define a number of buttons that will be used for starting, stopping, and resetting the animation. You also define the canvas where the animation will take place.

You may notice that there are two files referenced in <script> elements towards the end of this markup. The raf-polyfill.js file contains the polyfill that we looked at in the previous section. Make sure that you download this file and save it in the same folder as your index.html file. You will also need to copy the style.css file from the code download into your project folder.

Setting up the JavaScript

Now that you have your HTML and CSS sorted, it’s time to start writing the JavaScript code that will handle drawing the animation on the canvas. If you haven’t used the Canvas API before, don’t worry, I will explain everything you need to know as we go.

Create a new file in your project folder called script.js and add the following code to it.

Here you first create a variable called canvas and initialize it by fetching the <canvas> element in your markup. You then get a 2d drawing context for the canvas. This provides methods for drawing objects on the canvas as well as controlling the styling of those objects.

The next line of code sets the fillStyle property on the drawing context to #212121.

The requestID variable will be used to keep track of the requestID returned by the requestAnimationFrame method.

The posX, boxWidth, and pixelsPerFrame variables are used to set the position the box should be drawn on the canvas; the width of the box; and the number of pixels the box should be moved in each frame.

Finally you call the drawing contexts fillRect method, passing in the X and Y coordinates of the location the rectangle should be drawn along with its height and width.

Writing the animate Function

Next up you need to write the animate function which will be responsible for drawing frames.

The call to requestAnimateFrame at the top of this function will schedule the next animation frame. This is placed first so that we can get as close to 60FPS as possible when using the setTimeout fallback provided by the polyfill.

You then have an if statement that checks to see if the box has reached the right side of the canvas. If the box has not yet reached the end you use the clearRect method to remove the box drawn in the previous frame and then draw the box at it’s new position using fillRect. If the box has reached the end of the canvas, you call cancelAnimationFrame in order to cancel the frame scheduled at the start of the animate function. Finally, you update the posX variable with the position that the box should be drawn in the next frame.

Note: Notice that the parameters passed to clearRect only cover the position of the box in the previous frame. As we only have 16.67ms to finish drawing the frame it is best to do as little work as possible. Clearing the whole canvas (read: the lazy way) would take much longer than clearing just a small section of it.

We could have actually optimized this even further. How do you think this could have been achieved? Share your solutions in the comments.

Hooking up the Buttons

The final task you need to complete to get your demo working is to set up some event listeners for the start, stop, and reset buttons.

Here you have set up three event listeners. The first two are for starting and stopping the animation. The final event listener is fired when the reset button is clicked. This will set the posX variable to 0. It also clears the canvas – we’re not as concerned about performance so it’s okay to do this the lazy way – and draws the box back at it’s start position.

Your demo app is now complete! Open the index.html file in your browser and click the start button to see the animation.

Browser Support

Browser support for requestAnimationFrame is reasonably good. Firefox and Chrome have had support for a while now with Opera and IE adding support more recently. As long as you’re including the polyfill mentioned earlier in this post you should be okay to use requestAnimationFrame in your projects today.

Summary

The requestAnimationFrame method makes it really easy for developers to create smooth JavaScript animations for their websites. By delegating the handling of animation frames to the browser you are able to take advantage of a number of optimizations, all of which result in less resource usage and extended battery life on mobile devices.

What do you think about requestAnimationFrame? Share your thoughts in the comments.

If you click on the page you should see fireworks that shoot up from the bottom

Hello! We're the teachers here at Treehouse. We produce video courses on everything from web design and web development to iOS and business skills. You can browse our full library of content to find the course that's right for you.

In the meantime, explore the free features, tips, tricks and videos here on our blog. Tell us what you think, we'd love to chat: blog@teamtreehouse.com

Stay Updated

Sign up for our newsletter, and we'll send you news and tutorials
on web design, coding, business, and more! You'll also receive these
great gifts:

checkArt and the Web: Line, Shape, and Form - An eBook by Treehouse Teacher Nick Pettit.

checkOn Freelancing - An audiobook about running your own business by Simon Collison.

Swift is a new programming language created by Apple to program iOS apps. If you are new to programming or to Swift then this course is for you. Learn about programming concepts like: variables, types, collections and control structures.

Ruby is a programming language with a focus on simplicity and productivity, and it's used to create some of the biggest websites in the world. Learn how to work with Ruby and write simple Ruby programs in this introductory course.

Interested in creating Android apps? Learn the Java programming language, a tool for Android development called Android Studio, and some very basic concepts of the Android Software Development Kit, or SDK.

Bring your big idea to life! Learn how to start a company on the right foot with an introduction to basic business concepts, including corporate structure, marketing, finance, and accounting. Then you’re ready for more advanced business strategies.