Helping react-motion and animated to become best friends

react-spring

Helping react-motion and animated to become best friends.

What is it?

![spring](/content/images/2018/05/spring.gif) ![transitions](/content/images/2018/05/transitions.gif) ![trails](/content/images/2018/05/trails.gif)

![tree](/content/images/2018/05/tree.gif) ![sunburst](/content/images/2018/05/sunburst.gif) ![areas](/content/images/2018/05/areas.gif)

![gestures](/content/images/2018/05/gestures.gif) ![reveals](/content/images/2018/05/reveals.gif) ![morph](/content/images/2018/05/morph.gif)

![vertical](/content/images/2018/05/vertical.gif) ![horizontal](/content/images/2018/05/horizontal.gif) ![keyframes-trail](/content/images/2018/05/keyframes-trail.gif)

![dragndrop](/content/images/2018/05/dragndrop.gif) ![stream](/content/images/2018/05/stream.gif) ![time](/content/images/2018/05/time.gif)

A set of simple, spring-physics based primitives (as in building blocks) that should cover most of your UI related animation needs once plain CSS can't cope any longer. Forget easings, durations, timeouts and so on as you fluidly move data from one state to another. This isn't meant to solve each and every problem but rather to give you tools flexible enough to confidently cast ideas into moving interfaces.

Why do we need yet another?

react-spring is a cooked down fork of Christopher Chedeau's animated (which is used in react-native by default). It is trying to bridge it with Cheng Lou's react-motion. Although both are similarily spring-physics based they are still polar opposites.

Declarative Primitives Interpolations Performance
React-motion
Animated
React-spring

react-spring builds upon animated's foundation, casting its imperative side out, making it leaner and more flexible. It inherits react-motions declarative api and goes to great lengths to simplify it. It has lots of useful primitives, can interpolate mostly everything and last but not least, can animate by committing directly to the dom instead of re-rendering a component frame-by-frame.

Overview ?

Springs

A Spring will move data from one state to another. It remembers the current state, value changes are always fluid.

import { Spring } from 'react-spring'

<Spring from={{ opacity: 0 }} to={{ opacity: 1 }}>
    {styles => <div style={styles}>i will fade in</div>}
</Spring>

Mount/unmount Transitions

Transition watches elements as they mount and unmount, it helps you to animate these changes.

import { Transition } from 'react-spring'

<Transition
    keys={items.map(item => item.key)}
    from={{ opacity: 0, height: 0 }}
    enter={{ opacity: 1, height: 20 }}
    leave={{ opacity: 0, height: 0 }}>
    {items.map(item => styles => <li style={styles}>{item.text}</li>)}
</Transition>

2-state and 1-state Reveals

Given a single child instead of a list you can toggle between two components.

import { Transition } from 'react-spring'

<Transition from={{ opacity: 0 }} enter={{ opacity: 1 }} leave={{ opacity: 0 }}>
    {toggle ? ComponentA : ComponentB}
</Transition>

If you need to toggle a single child, that is also possible: {toggle && Component}

Trails and staggered animations

Trail animates the first child of a list of elements, the rest follow the spring of their previous sibling.

import { Trail } from 'react-spring'

<Trail from={{ opacity: 0 }} to={{ opacity: 1 }} keys={items.map(item => item.key)}>
    {items.map(item => styles => <div style={styles}>{item.text}</div>)}
</Trail>

Parallax and page transitions

Parallax allows you to declaratively create page/scroll-based animations.

import { Parallax, ParallaxLayer } from 'react-spring'

<Parallax pages={2}>
    <ParallaxLayer offset={0} speed={0.2}>
        first Page
    </ParallaxLayer>
    <ParallaxLayer offset={1} speed={0.5}>
        second Page
    </ParallaxLayer>
</Parallax>

Time/duration-based implementations and addons

You'll find varying implementations under /dist/addons. For now there's a time-based animation as well common easings, and IOS'es harmonic oscillator spring. All primitives understand the impl property which you can use to switch implementations.

import { TimingAnimation, Easing } from 'react-spring/dist/addons'

<Spring impl={TimingAnimation} config={{ delay: 200, duration: 1000, easing: Easing.linear }} ...>

Keyframes

Keyframes orchestrates animations in a script that you provide. Theoretically you can even switch between primitives, for instance going from a Spring, to a Trail, to a Transition. It tries its best to remember the last state so that animations are additive. Animation can be awaited and return current props. Be warned: the keyframe API is still highly experiemental and can be subject to changes.

import { Keyframes, Spring } from 'react-spring'

<Keyframes script={async next => {
    await next(Spring, { from: { opacity: 0 }, to: { opacity: 1 } })
    await next(Spring, { to: { opacity: 0 } })
}}>
    {styles => <div style={styles}>Hello</div>}
</Keyframes>

Render props, interpolation and native rendering ?

Render props

The Api is driven by render props (though we do expose imperative Api as well). By principle we offer both render and children as well as prop forwardwing (unrecognized props will be spread over the receiving component).

const Header = ({ children, bold, ...styles }) => (
    <h1 style={styles}>
        {bold ? <b>{children}</b> : children}
    </h1>
)

<Spring render={Header} to={{ color: 'fuchsia' }} bold={this.state.bold}>
    hello there
</Spring>

Interpolation

You can interpolate almost everything, from numbers, colors (names, rgb, rgba, hsl, hsla), paths (as long as the number of points match, otherwise use custom interpolation), percentages, units, arrays and string patterns:

<Spring to={{
    scale: toggle ? 1 : 2,
    start: toggle ? '#abc' : 'rgb(10,20,30)',
    end: toggle ? 'seagreen' : 'rgba(0,0,0,0.5)',
    stop: toggle ? '0%' : '50%',
    rotate: toggle ? '0deg' : '45deg',
    shadow: toggle ? '0 2px 2px 0px rgba(0, 0, 0, 0.12)' : '0 20px 20px 0px rgba(0, 0, 0, 0.5)',
    path: toggle ? 'M20,380 L380,380 L380,380 Z' : 'M20,20 L20,380 L380,380 Z',
    vector: toggle ? [1,2,50,100] : [20,30,1,-100],
}}>

GitHub