Awesome Mobile Animations
If you’ve been using apps and playing games on a modern smartphone recently, you might have noticed something that the best ones all have in common: awesome animations.
Take another look at your favourite apps and see how fluid they feel when you navigate around. Most likely, they’ve ditched dull, linear transitions and embraced fluent, charismatic motion.
For example, the game Dots uses this neat little effect throughout:
Just the addition of some acceleration, deceleration and a bounce effect turns a lifeless movement into something fluid and life-like.
Little things add up, too. For example, Yelp uses this rocket ship for their pull-to-refresh animation:
It might seem silly, but these little additions can help to surprise and delight our users.
Animations can also be used to orientate your users. For example, Moldiv uses this little animation to indicate how to access the menu:
Another example is the bounce effect when you tap the camera icon on the iPhone lock screen; it informs you that you need to swipe up.
Good apps also keep their animations consistent. Take Facebook’s Paper, for example. Here are some animations from different parts of the app, but all the transitions use the same effect of stretching out slightly further than their intended size, and then bouncing back:
So we can see that native mobile apps have been doing some awesome things with animations recently. What about the Web?
It might be harder to achieve similarly smooth results with our cross-platform Web technologies, but we’re seeing increasingly impressive results.
Let’s take a look at some examples…
Here’s a neat demo of React.js-powered CSS transitions. In particular, check out the menu effects from 0:43 and the photo gallery from 2:10:
Three.js is well-known for making WebGL development much easier, but it doesn’t just include a WebGLRenderer. It also has a CanvasRenderer, a CSS3DRenderer and more… Here’s a demo from the creator MrDoob using the CSS3DRenderer. It’s a take on famo.us’ periodic table:
CubeSlam is a very cool demo from Google and North Kingdom. On the desktop, it uses WebGL via Three.js, but on mobile they’re using their own CSS3D renderer:
About the tech: https://www.cubeslam.com/tech
Pixi.js is a fast graphics library for games and interactive animations. One of the best things about it is that you can set it up to use WebGL if it’s available (more on WebGL next), but if it’s not, automatically fall back to using regular HTML5 Canvas. Even Canvas without WebGL performs impressively fast though - just check out their Run Pixie Run demo:
Up until recently, WebGL hasn’t had great support from mobile browsers. But it’s available with Chrome for Android, Firefox for Android and Opera Mobile. And the big news just this week is that it’s coming to iOS 8!
Here’s a WebGL demo from Three.js. It runs really smoothly on my 2 year old Galaxy Nexus phone:
Pixi.js’ Bunnymark demo is really useful to demonstrate the difference that WebGL makes. Here it is without WebGL - just using the regular 2D Canvas context:
And here you can see the difference when WebGL is enabled:
Without WebGL, 1000 bunnies runs at 14 FPS (that’s sluggish). With WebGL, we get a very healthy 58 FPS.
So there’s various Web technologies that can help us to achieve great results, but we still need to be careful as developers and make sure we make the best use of the browsers’ power. Let’s run through some general tips:
1. For 60 frames per second, you only have 16ms to prepare each frame
60 frames per second is what we should be aiming for, to ensure a smooth experience for our users. That’s equivalent to the screen refresh rate of most mobile screens (60Hz) and good enough that our eyes won’t notice any flicker.
A lower frame rate (down to around 30 FPS) may be acceptable in some cases, but if we want the best performance, we should really aim for the top end.
16ms, as it sounds, is not very long! So…
2. Test, measure, optimise
You’ll need to keep a close eye on how your animations are performing. The debugging tools in your browser can provide the insights you need. For example, Chrome’s Timeline tab lets you record all the browser operations to do with rendering and see exactly how long they’re taking.
For a sense of how to use it, check out this video from Paul Irish where he identifies a specific performance problem and how to fix it:
You can also use the High Resolution Time API to accurately measure how long specific pieces of your code are taking.
Third party libraries can be useful too. For example, stats.js is a neat little FPS counter that you can place in a corner of your viewport. Especially handy for realtime performance measurement on mobile.
3. For now, define animations in CSS if possible
Until the new Web Animations API is available to use, you’ll get the best results if you can declare your animations in CSS. The browser will be better able to optimise them, running off the main UI thread and making use of the GPU.
4. Make sure you don’t hammer the UI thread
First of all, we should use requestAnimationFrame when it’s available, rather than setInterval or setTimeout (although a shim would need to fall back on one of those). This allows the browser to tell us when it’s ready to prepare the next frame. That means we can consistently run at the best frame rate the browser can manage, rather than trying to force a particular frame rate and finding that the browser either doesn’t keep up, or we don’t get the best out of it.
If you need to do a lot of processing, consider chunking it down and performing it incrementally inside your requestAnimationFrame callback. That way you can help ensure that you don’t go beyond that 16ms for each frame.
Another option could be to move your processing into a Web Worker.
5. Stick to: translate, scale, rotate, opacity
There are four properties that a browser can animate “cheaply”: translate, scale, rotate and opacity. Animate other things “at your own risk”.
Observe the difference here between animating the ‘top’ and ‘left’ properties (the one on the left), versus using ‘translate’ (the one on the right):
It really can make a very noticeable difference, on mobile devices especially.
6. Batch DOM operations
Manipulating the DOM invalidates layouts, meaning the browser has to perform reflows. So it’s best to avoid unnecessary DOM operations and to batch up those that you do need to make.
FastDOM is a little library that helps to batch DOM writes and reads. UI frameworks like React and Ractive can also handle this for you, by providing a Virtual DOM. They can determine the minimal set of changes that need to be made to the real DOM and modify it only at the best times.
Awesome mobile web animations? Yes we can
The text from Pete Hunt’s React Touch demo sums things up nicely:
“The web isn’t as performant as native, but on modern devices we can get pretty close. Or at least a lot better than the Web’s current reputation.”
So let’s ditch those boring animations and make our mobile web apps more fluid, and more awesome!