Creating Animations and Interactions with Physical Models
Physics-based animations and interactions are becoming more common in UI. This page goes through some basic physical models and the kinds of interactions and animations that can be constructed from them.
Scrolling on iOS is an excellent example of a physics-based interaction. When you drag your finger across the screen, the content tracks along with it, thereby scrolling, but when you lift your finger all of the physics magic happens: the content continues tracking with the same momentum and slows down under the influence of (virtual) friction. If you hit the end of the content, then the momentum goes into an overdamped spring which absorbs the momentum and returns you to the end of the content.
Everyone is familiar with scrolling, and all of the touch-based operating systems implement it because it feels so natural to use. But lets start with something a bit simpler: here are two buttons which get a bit smaller when you push down on them (to give visible feedback indicating that the UI has received your touch input). One of these buttons uses an underdamped spring to control its size, while the other uses more traditional CSS transitions.
- Push on each button periodically. Try setting the damping to 1 and see how large you can make the button.
- How does the spring constant relate to the speed of motion when you have a small damping? How are damping and the spring constant related?
In the button example above, the user input is a binary press (the button is either being pressed or not). In most of the other examples on this page, we'll instead seed the physics simulation with the current momentum and position of an object. To simplify the code, I always use a mass of 1, which means that velocity and momentum are the same number and thus interchangeable.
Why is it important to conserve momentum, though? What happens if we create animations that ignore the momentum that the user imparted to the UI?
This example is the UI for navigating back in Android Wear: you drag from the left to the right and release. One version ignores your momentum and just runs the same animation every time. The other example rolls the momentum into an constant acceleration (gravity) simulation if you drag with enough velocity or beyond the half-way point. If you don't drag far enough or drag in the other direction then a spring is used to take the menu back to where it started.
- How does it feel when the menu continues moving with the momentum that you gave it? How about when it just uses the canned transition?
- I used two physical simulations here, picking one depending on the velocity and end position. I started out using a single spring to do everything. That didn't work out because the cancel animation was too slow, so next I tried using one spring for "back" and one spring for cancelling the gesture. I then decided that maybe constant acceleration would feel better, and that's what is in there now. One nice thing about modeling with physical objects is that you have a lot of choice over how to make things behave.
Recent research suggests we have an understanding of conservation of momentum from birth. I believe that UI which upholds these strongly held expectations is more pleasing than UI that ignores them.
We're going to look at three simple simulations: springs, constant acceleration (or gravity) and friction. These sound pretty boring, but combined with touch we can come up with some good interactions.
In this example we're using gravity to create a lock screen like the one in Windows 8. When you drag up on the image and release, it keeps its momentum but is pulled down by a constant acceleration. If you don't give it enough momentum, then it falls back down and the machine stays locked. This is a physics-based variant of slide-to-unlock.
- Try slamming the lock screen into the ground!
- What happens when you set the Rebound to 1.0? What about 1.1?
- Press "Reset Position" and then try setting the acceleration to a negative value. Now we've changed the UI so that any upwards drag will unlock the machine—like hiding the notification list on Android or iOS. Physics simulations can give a very different feel depending on these constants.
Now we're going to compare constant deceleration (which is almost the same as the gravity example above; it just means the acceleration constant is negative) with friction. When I first started learning about physics simulations I thought that the constant deceleration simulation was the only way to slow things down and used it for everything, including scrolling. The result was terrible! My scrolling content would stop too abruptly and have a bad feel compared to everyone else's. For scrolling, as well as sliders, friction is a much better feeling simulation.
One way to think of the difference between deceleration and friction is to visualize the way an object slows down when you throw it up into the air before it starts falling again (this is constant deceleration) and the way an object slows down after it's been pushed along a table like an air-hockey puck when the table is off (friction). For the mathematically inclined, constant deceleration is a quadratic function of time whereas friction is a power function where time is the exponent.
In this example you can see the difference between constant deceleration and friction. Give each of the sliders a short, slow fling and watch how they slow down.
- Notice how the Decelerating Slider (which is using a constant deceleration) doesn't feel good. Either it goes too far or stops too abruptly. Gravity was the perfect simulation for the lock screen (and the dialogs below) but friction creates a much more natural feel for these sliders and for scrolling.
- When the thumb hits the end of the slider it just stops moving, and all momentum is immediately lost. What can we do so that we're not throwing away all of the thumb's momentum? We could drag the whole control, we could let the thumb go over the end slightly, or we could even squish the thumb a bit!
So far we've used individual simulations (spring, gravity and friction) to create various interactions and animations. We can actually combine them to create even more interesting systems. In my recent game for Android, Letterplex, I made the dialogs fall from the top of the screen and land in the middle (as they do in the iOS inspiration Letterpress). However when they reach the middle of the screen, they bounce slightly as if landing on a cloud (or an overdamped spring).
In this non-interactive example you can see how the combination of gravity and a spring makes a nice feeling animation. Hit "Reset Position" to start the animation over.
- Notice how this combination is very sensitive to the damping value—try setting it to 1. Even though momentum is conserved we get something that feels distinctly weird, like a fly falling into a spider's web.
- Play with the acceleration and spring constant to get a feel for how the gravity and spring constants interact. A high spring constant gives us something like NeXT's "head shaking" log in dialog, only vertically.
Perhaps the most significant combination is friction with a spring to create scrolling. You've certainly seen this before, but try changing the coefficient of friction and the spring constants to better understand the kinds of systems you can create with these simple primitives.
- Try setting the friction to the smallest value (0.001) and the largest value (0.1) and notice how it changes how far your flicks cause the list to scroll. iOS actually uses different friction coefficients in different places—In Contacts your flicks take you a lot further than they do in Safari, for example.
Once you understand how something like scrolling is constructed, it's easy to make things like the "infinite" linear scroller in iTunes Radio on iOS 7. Here we have a constant velocity giving us a linear animation. Note: If you think you might ever drop a frame, don't use linear translation animations. Humans are amazing at tracking linear motion, so dropped frames will be perceived as very jarring. In contrast, humans seem bad at tracking things zooming in or out, so you can drop all kinds of frames in a zoom animation and most people won't notice.
This example uses a tweaked friction simulation that has a constant velocity which can be temporarily overcome by flicking left or right. Notice what happens when your imparted momentum is consumed and the scroller resumes its previous motion. It's smooth and seamless.
Mapping inputs and outputs
So far we've used press and velocity as inputs, and we've mapped the output of the physics simulation to either the translation or scale of the object. Our devices have a bunch of sensors and we can control more than just the initial velocity.
Here's an example where (on mobile only) we use the gyroscope to control the velocity to pan around in a photo. This is similar to Facebook Paper's photo viewer, but Facebook Paper uses a direct relationship between the gyro and the scroll position.
Note that this example only works on devices with gyroscopes.
- Is it annoying when you're trying to hold the photo still? We could add a dead zone in the middle of the gyroscope output where we round it to zero to improve this.
- I initially wrote this example with the gyroscope controlling acceleration. This felt terrible! It would accelerate off left or right, and you'd overcompensate in the other direction. Controlling the velocity feels pretty good, and moves smoothly even though the gyroscope is a fairly noisy sensor.
We can also trigger springs based on proximity. I wrote up this example previously. Each face circle has a spring which is triggered when the cursor gets close. The motion of the face is then controlled by both the spring and the cursor position: the spring controls how far the face should be between its natural home position and where the cursor currently is.
Phew! Here's an example of mapping the output of a physics system differently. It's the "falling dialog" example from above, except that instead of translating the dialog downwards when it hits the ground, we squish it. Non-uniform scales don't usually look very pleasing, so it's hard to find any examples like this in real products.
Adding extra effects
Sometimes you've got a good looking animation or interaction, but you want to add something extra to it that is non-physical. Here's an example of adding a rotation to the falling dialog to make it look less one-dimensional. The question and answer app Jelly uses this to good effect when animating the question cards.
What did we learn?
- Physical models let us easily create rich animations and interactions that feel more natural by conforming to our innate expectations of how things should move and respond.
- Physical models give us enough flexibility to create a wide variety of interactions and animations.
- Physical models can be combined to create more complex and dynamic systems.
- We can use all kinds of inputs to physical models, and map their results differently to create the effects we want.
I made a lot of mistakes and rewrote a couple of examples while writing this article (read my mistakes in the commit log). What did I learn?
- I didn't have a good grasp on what the spring constant and damping do to the "feel" of the spring before writing this. I had a solid algebraic understanding of a spring, but lacked a good intuitive understanding. That's the strength of interactive examples!
- The CSS transition version of the Android Wear back gesture actually works better than I expected, so the difference between the two versions is more subtle than I wanted. As I noted above, I also tried using a spring to model it at first, and later switched to acceleration which feels a lot better!
- Don't map the gyroscope to acceleration for panning! It was obvious what I needed to do as soon as I saw it running, but it wasn't obvious to me before.
- The squishy dialog is neat! I thought it'd look really bad, but I actually quite like it. Coincidentally squash and stretch is the most important of Disney's 12 Principles of Animation.
About the author
Ralph Thomas is a former high-school physics student who has spent the past 15 years focused on user interface implementation. A "full-stack" client engineer, Ralph has written high-performance mobile UIs from kernel input drivers, through OpenGL ES-based 2D graphics engines, physics engines and user interface toolkits up to full applications built on those foundations. Ralph has also contributed performance enhancements to the WebKit project. Follow Ralph on Twitter
or send him email