react-motion README

The project's README from github.com/chenglou/react-motion. As one markdown file: README.md.

React-Motion

Build Status npm version Bower version react-motion channel on discord

import {Motion, spring} from 'react-motion';
// In your render...
<Motion defaultStyle={{x: 0}} style={{x: spring(10)}}>
  {value => <div>{value.x}</div>}
</Motion>

Animate a counter from 0 to 10. For more advanced usage, see below.

Install

{
  "dependencies": {
    "react-motion": "https://unpkg.com/react-motion/bower.zip"
  }
}

then include as

<script src="bower_components/react-motion/build/react-motion.js"></script>
<script src="https://unpkg.com/react-motion/build/react-motion.js"></script>
(Module exposed as `ReactMotion`)

Works with React-Native v0.18+.

Demos

Check the wiki for more!

Try the Demos Locally

git clone https://github.com/chenglou/react-motion.git
cd react-motion
npm install

To build the repo yourself: npm run prepublish.

What does this library try to solve?

My React-Europe talk

For 95% of use-cases of animating components, we don't have to resort to using hard-coded easing curves and duration. Set up a stiffness and damping for your UI element, and let the magic of physics take care of the rest. This way, you don't have to worry about petty situations such as interrupted animation behavior. It also greatly simplifies the API.

This library also provides an alternative, more powerful API for React's TransitionGroup.

API

Exports:

Here's the well-annotated public Flow type definition file (you don't have to use Flow with React-motion, but the types help document the API below).

P.S. using TypeScript? Here are the React-motion TypeScript definitions!


Helpers

- spring: (val: number, config?: SpringHelperConfig) => OpaqueConfig

Used in conjunction with the components below. Specifies the how to animate to the destination value, e.g. spring(10, {stiffness: 120, damping: 17}) means "animate to value 10, with a spring of stiffness 120 and damping 17".

- Presets for {stiffness, damping}

Commonly used spring configurations used like so: spring(10, presets.wobbly) or spring(20, {...presets.gentle, precision: 0.1}). See here.


<Motion />

Usage

<Motion defaultStyle={{x: 0}} style={{x: spring(10)}}>
  {interpolatingStyle => <div style={interpolatingStyle} />}
</Motion>

Props

- style: Style

Required. The Style type is an object that maps to either a number or an OpaqueConfig returned by spring() above. Must keep the same keys throughout component's existence. The meaning of the values:

- defaultStyle?: PlainStyle

Optional. The PlainStyle type maps to numbers. Defaults to an object with the same keys as style above, whose values are the initial numbers you're interpolating on. Note that during subsequent renders, this prop is ignored. The values will interpolate from the current ones to the destination ones (specified by style).

- children: (interpolatedStyle: PlainStyle) => ReactElement

Required function.

- onRest?: () => void

Optional. The callback that fires when the animation comes to a rest.


<StaggeredMotion />

Animates a collection of (fixed length) items whose values depend on each other, creating a natural, springy, "staggering" effect like so. This is preferred over hard-coding a delay for an array of Motions to achieve a similar (but less natural-looking) effect.

Usage

<StaggeredMotion
  defaultStyles={[{h: 0}, {h: 0}, {h: 0}]}
  styles={prevInterpolatedStyles => prevInterpolatedStyles.map((_, i) => {
    return i === 0
      ? {h: spring(100)}
      : {h: spring(prevInterpolatedStyles[i - 1].h)}
  })}>
  {interpolatingStyles =>
    <div>
      {interpolatingStyles.map((style, i) =>
        <div key={i} style={{border: '1px solid', height: style.h}} />)
      }
    </div>
  }
</StaggeredMotion>

Aka "the current spring's destination value is the interpolating value of the previous spring". Imagine a spring dragging another. Physics, it works!

Props

- styles: (previousInterpolatedStyles: ?Array<PlainStyle>) => Array<Style>

Required function. Don't forget the "s"!

- defaultStyles?: Array<PlainStyle>

Optional. Similar to Motion's defaultStyle, but an array of them.

- children: (interpolatedStyles: Array<PlainStyle>) => ReactElement

Required function. Similar to Motion's children, but accepts the array of interpolated styles instead, e.g. [{x: 5}, {x: 6.4}, {x: 8.1}]

(No onRest for StaggeredMotion because we haven't found a good semantics for it yet. Voice your support in the issues section.)


<TransitionMotion />

Helps you to do mounting and unmounting animation.

Usage

You have items a, b, c, with their respective style configuration, given to TransitionMotion's styles. In its children function, you're passed the three interpolated styles as params; you map over them and produce three components. All is good.

During next render, you give only a and b, indicating that you want c gone, but that you'd like to animate it reaching value 0, before killing it for good.

Fortunately, TransitionMotion has kept c around and still passes it into the children function param. So when you're mapping over these three interpolated styles, you're still producing three components. It'll keep interpolating, while checking c's current value at every frame. Once c reaches the specified 0, TransitionMotion will remove it for good (from the interpolated styles passed to your children function).

This time, when mapping through the two remaining interpolated styles, you'll produce only two components. c is gone for real.

import createReactClass from 'create-react-class';

const Demo = createReactClass({
  getInitialState() {
    return {
      items: [{key: 'a', size: 10}, {key: 'b', size: 20}, {key: 'c', size: 30}],
    };
  },
  componentDidMount() {
    this.setState({
      items: [{key: 'a', size: 10}, {key: 'b', size: 20}], // remove c.
    });
  },
  willLeave() {
    // triggered when c's gone. Keeping c until its width/height reach 0.
    return {width: spring(0), height: spring(0)};
  },
  render() {
    return (
      <TransitionMotion
        willLeave={this.willLeave}
        styles={this.state.items.map(item => ({
          key: item.key,
          style: {width: item.size, height: item.size},
        }))}>
        {interpolatedStyles =>
          // first render: a, b, c. Second: still a, b, c! Only last one's a, b.
          <div>
            {interpolatedStyles.map(config => {
              return <div key={config.key} style={{...config.style, border: '1px solid'}} />
            })}
          </div>
        }
      </TransitionMotion>
    );
  },
});

Props

First, two type definitions to ease the comprehension.

- styles: Array<TransitionStyle> | (previousInterpolatedStyles: ?Array<TransitionPlainStyle>) => Array<TransitionStyle>

Required. Accepts either:

- defaultStyles?: Array<TransitionPlainStyle>

Optional. Similar to the other components' defaultStyle/defaultStyles.

- children: (interpolatedStyles: Array<TransitionPlainStyle>) => ReactElement

Required function. Similar to other two components' children. Receive back an array similar to what you provided for defaultStyles, only that each style object's number value represent the currently interpolating value.

- willLeave?: (styleThatLeft: TransitionStyle) => ?Style

Optional. Defaults to () => null. The magic sauce property.

- didLeave?: (styleThatLeft: {key: string, data?: any}) => void

Optional. Defaults to () => {}.

- willEnter?: (styleThatEntered: TransitionStyle) => PlainStyle

Optional. Defaults to styleThatEntered => stripStyle(styleThatEntered.style). Where stripStyle turns {x: spring(10), y: spring(20)} into {x: 10, y: 20}.

Note that willEnter and defaultStyles serve different purposes. willEnter only triggers when a previously inexistent TransitionStyle inside styles comes into the new render.

(No onRest for TransitionMotion because we haven't found a good semantics for it yet. Voice your support in the issues section.)


FAQ

Hard-coded duration goes against fluid interfaces. If your animation is interrupted mid-way, you'd get a weird completion animation if you hard-coded the time. That being said, in the demo section there's a great Spring Parameters Chooser for you to have a feel of what spring is appropriate, rather than guessing a duration in the dark.

You don't. Unless you put it in another TransitionMotion...

See StaggeredMotion

React string refs won't work:

<Motion style={...}>{currentValue => <div ref="stuff" />}</Motion>

This is how React works. Here's the callback ref solution.

react-motion (chenglou/react-motion)

Searching Database…

Что это такое?react-motion — это библиотека анимаций для React, которая использует физику пружины вместо жестко заданных длительностей и кривых плавности для анимации компонентов.
Это фреймворк или библиотека?Это библиотека, которую импортируют в приложение React. Она экспортирует компоненты и вспомогательные функции: spring, Motion, StaggeredMotion, TransitionMotion и presets.
Как добавить её в проект?Установите командой npm install --save react-motion, затем оберните значения, которые хотите анимировать, функцией spring() внутри компонента Motion, StaggeredMotion или TransitionMotion.
Нужен ли Bower или что-то особенное для установки?Нет, рекомендуемый способ — npm. В README прямо предупреждается против использования Bower.
Как управлять скоростью или длительностью анимации?Настройки длительности нет. Вы подбираете жесткость и демпфирование пружины (по умолчанию 170 и 26), а для поиска подходящих значений используйте входящее демо Spring Parameters Chooser.
Это работает только в веб-React или также в React Native?Работает и в React Native, начиная с версии 0.18, а также в обычном веб-React через npm или подключение скрипта на странице.
Для чего нужен StaggeredMotion?Он анимирует коллекцию элементов фиксированной длины, где значение пружины каждого элемента зависит от предыдущего. Так создается естественный эффект последовательного появления вместо жестко заданных задержек.
Для чего используется TransitionMotion?Он обрабатывает анимации появления и исчезновения элементов: удерживает их на экране (например, анимируя до 0) и только затем окончательно удаляет через колбэки willLeave и willEnter.
Есть ли готовые пресеты пружин, которые можно использовать?Да, в библиотеку входят именованные пресеты, например wobbly и gentle. Их можно использовать так: spring(10, presets.wobbly).
Почему бы просто не задать длительность анимации жестко?Жестко заданные длительности ломаются, когда анимация прерывается на полпути, и завершение выглядит странно. Пружины на основе физики корректно обрабатывают прерывания.
Creator
chenglou
Size
5.2 MB
Stars
21.9K
Age
11y
Commits · 90 Days