So far we’ve only really covered CSS for animation. From this point forward we’re going to move primarily into JavaScript—but before we do, I think it’s important to weigh all of the options you have for working in animation on the web, and the pros and cons of each, so that you know what you’re using and can pick the best tool for the job.
At the end of the chapter we’ll discuss the same tools in terms of their integration with React, primarily because they work a little differently in a React environment due to the virtual DOM.
There’s no possible way to cover every single animation library, so I will stick with those that I’ve used or that interest me a lot. Please keep in mind that these recommendations are based on my own experiences; you may have a different experience or opinion, and that’s OK.
Before we talk about libraries, let’s go over some native implementations. Most libraries use native animation technologies under the hood, so the more that you know about them, the better you’ll be able to understand what’s happening when the animation is abstracted.
The reason we go over CSS so much in the beginning is because it can tend to be the Occam’s razor of web animation technologies—all things being equal, the simplest solution is sometimes the best, especially if you need to get something up and running quickly. CSS animations make it possible to transition between different states using a set of keyframes.
Pros:
nth:child
pseudoclasses in functions. Variables also allow for things like easing functions that you’d like to remain consistent.onAnimationEnd
and some other animation hooks with native JavaScript.Cons:
requestAnimationFrame()
(rAF for short) is a native method available on the window
object in JavaScript. It’s really wonderful because under the hood, it figures out what the appropriate frame rate is for your animation in whatever environment you’re in, and only pushes it to that level. For instance, when you’re on mobile, it won’t use as high a frame rate as on desktop. It also stops running when a tab is inactive, to keep from using resources unnecessarily. For this reason, requestAnimationFrame()
is a really performant way of animating, and most of the libraries we’ll cover use it internally.
requestAnimationFrame()
works in a similar fashion to recursion; before it draws the next frame in a sequence, it executes the logic, and then calls itself again to keep going. That might sound a little complex, but what it really means is that you have a series of commands that are constantly running, so it will interpolate how the intermediary steps are rendered for you very nicely.
There’s more information about requestAnimationFrame()
in Chapter 15, so if you’re interested in learning more, flip ahead.
Despite the fact that canvas is raster-based and SVG is vector-based, you can still work with SVGs in canvas. Because it is raster-based, though, the SVGs won’t look as crisp as they normally do without a little bit of extra work:
var canvas = document.querySelector('canvas'), ctx = canvas.getContext('2d') pixelRatio = window.devicePixelRatio, w = canvas.width, h = canvas.height; canvas.width = w * pixelRatio canvas.height = h * pixelRatio ctx.arc ( canvas.width / 2, canvas.height / 2, canvas.width / 2, 0, Math.PI * 2 ) ctx.fill(); canvas.style.width = w + 'px';
It doesn’t take much code, but if you’re used to SVG being resolution-independent, this can be a small gotcha. There’s a great video on egghead that breaks this down.
I don’t work with SVGs in this environment much, but I’ve seen Tiffany Rayside and Ana Tudor do some great stuff on CodePen with it. It’s worth exploring their profiles.
The Web Animations API is a common language for browsers and developers to describe animations on DOM elements, in native JavaScript. This allows you to create more complex sequential animations without loading any external scripts (or it will, anyway, when support climbs—for now, you’ll probably need a polyfill). This API was created to distill all of the great libraries and work that people were already making with JavaScript. The Web Animations API is part of a movement to align the performance of CSS animations and the flexibility of sequencing in JavaScript under one roof, natively.
Pros:
Cons:
GreenSock is currently the most sophisticated animation library on the web, and I favor working with it. Please understand that this bias comes from working, playing around with, and bumping my head badly on a lot of different animation tooling, so when I give my strong endorsement, it’s through blood, sweat, and tears. I especially like it for SVG. The GreenSock Animation API has almost too many cool benefits to list here without missing something, but they have extensive docs and forums you can explore.
Pros:
Cons:
Mo.js is a library by an awesome fellow, Oleg Solomka, who goes by LegoMushroom. He’s an extremely talented animator, and has already made some awesome demos for this library that have me really excited. The library is still in beta, but it’s getting very close to being released now. See Chapter 13 for more details on how to use it.
Pros:
Cons:
Bodymovin’ is meant for building animations in Adobe After Effects that you can easily export to SVG and JavaScript. Some of the demos are really impressive. I don’t work with it because I really like building things from scratch with code (so this defeats the purpose for me), but if you’re more of a designer than a developer, this tool would probably be really great for you. The only con I really see to that part is that if you change it later, you’d have to re-export it, so it might be a weird workflow. Also, outputted code is usually kind of gross, but I haven’t seen that affect the performance too much, so it’s probably fine.
SMIL (Synchronized Multimedia Integration Language) is the native SVG animation specification: it allows you to move, morph, and even interact with SVGs directly within the SVG DOM. There are a ton of pros and cons to working with SMIL, but the biggest one will lead me to omit it entirely: it’s losing support. I wrote a post on how to transfer over to better-supported techniques to get you going, though.
Velocity offers a lot of the sequencing that GreenSock does, but without a lot of the bells and whistles. I no longer really use Velocity due to the cons listed here. Velocity’s syntax looks a bit like jQuery, so if you’ve already been using jQuery, the familiarity might be a big boon for you.
Pros:
Cons:
A lot of people think of Snap as an animation library, but it’s really not. I was going to run performance benchmarks on Snap, but even Dmitri Baranovskiy (the incredibly smart and talented author of this library, and its predecessor, Rafael) says on the SVG Immersion Podcast that it’s not the correct tool for this. In a personal message to me, he said, “Just a note: Snap is not an animation library and I always suggest to use it with GSAP when you need a serious animation.”
That said, jQuery is not great with SVG, though it does now support class operations. If you need to do a lot of DOM manipulation with SVG, Snap is a recommended tool.
There is a library called SnapFoo that extends Snap’s realm to animation. I haven’t played with it myself yet, but it looks pretty cool.
Before we talk about React, let’s cover why we have to treat animations in React differently. The main difference lies in the Document Object Model (DOM), which is how we create a structured document with objects, and is mostly expressed as a tree.
React has a virtual DOM, which is an abstraction of this structure. React does this for a number of reasons, the most compelling of which to me is the ability to figure out what’s changed and update only the pieces it needs to. This abstraction comes at a price, of course, and some of the old tricks that you’re used working with will give you trouble in a React environment. jQuery, for instance, will not play nice with React, as its primary function is to interact with and manipulate the browser’s native DOM. But I’ve even seen some strange CSS race conditions. Here are some of my recommendations for nice animations in a React workflow.
React-Motion by Cheng Lou is considered to be the best way to animate in React, and the community has pretty much adopted it over the old ReactCSSTransitionGroup
. I like React-Motion a lot, but there are some keys to working with it that will have you banging your head for a little while if you don’t get them.
React-Motion is pretty similar to game-based animation, where you give an element mass and physics and send it on its way, and it gets there when it gets there—you aren’t specifying an amount of time like you do with CSS or any other traditional web-based sequential motion. The motion can look realistic, which can be beautiful. But the hard part is that if you have two different things that have to fire at the same time and get there at the same time, it can be tough to line them up exactly.
Recently, Cheng Lou added in onRest
, which allows for this kind of callback workflow. It hasn’t advanced much, though, as it’s counter to the original premise of the tool. It’s still not easy to write a loop (without writing an infinite loop, which is bad for a whole slew of reasons). You might never come across this use case, but I did once.
Pros:
Cons:
onRest
still doesn’t work for staggering parameters.GreenSock has so much to offer that it’s still worth using in a React environment. It takes a bit more finessing than usual, and some things that should work (and do with the DOM) don’t in React. That said, I’ve gotten it working a few different ways:
onClick
.ReactTransitionGroup
, which is a pretty cool way of doing it.Canvas itself works beautifully in React. You can choose to bypass the DOM entirely and attach a single node, in which you can create all of your animations. It has the same benefits and limitations we discussed previously (see “Canvas”). You can also break a canvas into React components, but the implementation details can get much more complicated due to the virtual DOM.
There are a couple of good libraries for working with canvas in React. React-Canvas was developed by the Flipboard team because they wanted 60 fps animation with the DOM. The repo hasn’t been updated in a while, though, and it really does focus on only UI elements, so any other kind of animation will take some work.
React Konva is an interesting, very declarative way of working with canvas and React. It creates beautiful shapes incredibly easily, but the animation performance is a little lacking. The developer acknowledges this right in the docs, so it’s possible that if you’re willing to submit a pull request (PR) you could improve it and help him work on it.
CSS has had a resurgence lately because it’s likely the easiest way to create animations in React. I like working with CSS animations for little things like UI/UX interactions, but have seen them behave a little strangely if you try to chain things using delays. Other than that, they’re pretty great, especially for small UI adjustments.
Unfortunately, it would be impossible to go into all of these wonderful tools in great depth—this book would be 10 times as long! We’ll focus primarily on the GreenSock Animation API, due to its power and multitude of uses. We’ll also cover mo.js, React-Motion, and requestAnimationFrame()
so you know how to work with JavaScript at a bare-metal level.
13.58.113.193