React-motion 101: Springs

Which one is the odd one out?

Boxes 1, 3 and 4 all used different timing functions (ease-in, ease-out, linear). However, they were all timed animations set to run for 500ms.

Box 2 is different. The animation wasn’t set to run for a certain time. Instead the law of physics, in particular a spring, was used to create the animation. You can tell a spring was used because towards the end of the animation, it takes a while for the box to settle into its final position. The difference becomes even more apparent if we interrupt the animation. Box 1, 3 and 4 animation will look a bit jarring if we interrupt it. Box 2 on the other hand handles the change gracefully and naturally springs into its new position (play around with these values on codepen)

Stiffness and damping to change animation

In a spring animation, there are two variables you can control: stiffness and damping. Changing these two variables will result in a different feel to the animation.

Stiffness defines how strong the object is pulled towards its final value.

Damping is the friction the object will encounter as it gets pulled towards its target.

Changing these two values will result in a completely different feel to an animation.

The below examples can be tweaked in this code pen


low stiffness

A low stiffness value means that the object will be pulled slowly towards its final position as seen on the left.

A high stiffness value means that the object will get pulled quickly towards the final position .


Low damping

Low damping value will mean that there will be a lot more bounce.

In fact with no damping (0 value), the object will oscillate on the spring forever.


High damping

A high damping value means there is a lot of friction. This means the object is significantly slowed down while being pulled towards the spring. In this way we prevent a bouncing effect.


React motion provides a bunch of presets for stiffness and damping:

  • no wobble
  • gentle
  • wobbly
  • stiff

You can have a look at how these perform as well with the above examples in this codepen

React-motion examples with <Motion>

Let’s look at a couple of examples of using a spring animation with react-motion. We will just change one property of a div to create a variety of animation effects.

We will make use of the Motion component of react-motion in the examples.


Zoom in and out

Zoom in with scale3d
const config = { stiffness: 140, damping: 14 };
const toCSS = (scale) => ({ transform: `scale3d(${scale}, ${scale}, ${scale})` })
<Motion 
defaultStyle={{ scale: 0 }}
style={{ scale: spring(1, config) }}
>
{
(value) => <div className="box" style={toCSS(value.scale)} />
}
</Motion>

The default style sets the starting value of scale to 0%. The style prop will pull the scale value towards 100% using the spring function. Within the Motion component we use the value that is passed to us { (value) => ... } to calculate the CSS scale property. This will give the effect of the box zooming in.


Flip in

Using the same principles as above, except that we change the rotation of the box instead of the scale.

const toCSS = (rotateX) => ({ transform: `rotateX: ${rotateX}deg` })
<Motion 
defaultStyle={{ rotateX: 220 }}
style={{ rotateX: spring(0, config) }}
>
{
(value) => <div className="box" style={toCSS(value.rotateX)} />
}
</Motion>

Slide in

Slide in by changing the box’s x position

const toCSS = (rotateX) => ({ transform: `translateX: ${translateX}px` })
<Motion 
defaultStyle={{ translateX: 220 }}
style={{ translateX: spring(0, config) }}
>
{
(value) => <div className="box" style={toCSS(value.translateX)} />
}
</Motion>

More examples on codepen


Summary

Timed animations have their place and are often the first thing we look for when creating animations. Spring based animations are a good alternative for many of these types of animations. They deal much better with interruptions to the animations, don’t resort to needing to hard code duration and timing functions of animations.

Use spring animations when you want

  • Natural looking animations
  • Interruptible animations
    When an animation has not completely come to a stop and the user changes the system again, the animation can handle it gracefully and everything looks natural
  • Dynamic values
    Unlike CSS transitions where we hand off the transition to the browser, we have constant access to the animation values and can make changes to it as needed.

Disadvantages of spring based animations

  • Tuning the spring
    It takes a bit of “tuning” the stiffness and damping variables to get to the right feel of the animation
  • Not suitable for all types of animations (i.e. an object starting at slow pace and racing off the screen)
  • Can take a while to understand react-motion API

Further reading