Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

3 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. # React-Motion
  2. [![Build Status](https://travis-ci.org/chenglou/react-motion.svg?branch=master)](https://travis-ci.org/chenglou/react-motion)
  3. [![npm version](https://badge.fury.io/js/react-motion.svg)](https://www.npmjs.com/package/react-motion)
  4. [![Bower version](https://badge.fury.io/bo/react-motion.svg)](http://badge.fury.io/bo/react-motion)
  5. [![react-motion channel on discord](https://img.shields.io/badge/discord-react--motion%40reactiflux-738bd7.svg?style=flat)](https://discordapp.com/invite/0ZcbPKXt5bYzmcI0)
  6. ```js
  7. import {Motion, spring} from 'react-motion';
  8. // In your render...
  9. <Motion defaultStyle={{x: 0}} style={{x: spring(10)}}>
  10. {value => <div>{value.x}</div>}
  11. </Motion>
  12. ```
  13. Animate a counter from `0` to `10`. For more advanced usage, see below.
  14. ### Install
  15. - Npm: `npm install --save react-motion`
  16. - Bower: **do not install with `bower install react-motion`, it won't work**. Use `bower install --save https://unpkg.com/react-motion/bower.zip`. Or in `bower.json`:
  17. ```json
  18. {
  19. "dependencies": {
  20. "react-motion": "https://unpkg.com/react-motion/bower.zip"
  21. }
  22. }
  23. ```
  24. then include as
  25. ```html
  26. <script src="bower_components/react-motion/build/react-motion.js"></script>
  27. ```
  28. - 1998 Script Tag:
  29. ```html
  30. <script src="https://unpkg.com/react-motion/build/react-motion.js"></script>
  31. (Module exposed as `ReactMotion`)
  32. ```
  33. **Works with React-Native v0.18+**.
  34. ### Demos
  35. - [Simple Transition](http://chenglou.github.io/react-motion/demos/demo0-simple-transition)
  36. - [Chat Heads](http://chenglou.github.io/react-motion/demos/demo1-chat-heads)
  37. - [Draggable Balls](http://chenglou.github.io/react-motion/demos/demo2-draggable-balls)
  38. - [TodoMVC List Transition](http://chenglou.github.io/react-motion/demos/demo3-todomvc-list-transition)
  39. - [Photo Gallery](http://chenglou.github.io/react-motion/demos/demo4-photo-gallery)
  40. - [Spring Parameters Chooser](http://chenglou.github.io/react-motion/demos/demo5-spring-parameters-chooser)
  41. - [Water Ripples](http://chenglou.github.io/react-motion/demos/demo7-water-ripples)
  42. - [Draggable List](http://chenglou.github.io/react-motion/demos/demo8-draggable-list)
  43. [Check the wiki for more!](https://github.com/chenglou/react-motion/wiki/Gallery-of-third-party-React-Motion-demos)
  44. ### Try the Demos Locally
  45. ```sh
  46. git clone https://github.com/chenglou/react-motion.git
  47. cd react-motion
  48. npm install
  49. ```
  50. - With hot reloading (**slow, development version**): run `npm start`.
  51. - Without hot reloading (**faster, production version**): run `npm run build-demos` and open the static `demos/demo_name/index.html` file directly. **Don't forget to use production mode when testing your animation's performance**!
  52. To build the repo yourself: `npm run prepublish`.
  53. ## What does this library try to solve?
  54. [My React-Europe talk](https://www.youtube.com/watch?v=1tavDv5hXpo)
  55. 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.
  56. This library also provides an alternative, more powerful API for React's `TransitionGroup`.
  57. ## API
  58. Exports:
  59. - `spring`
  60. - `Motion`
  61. - `StaggeredMotion`
  62. - `TransitionMotion`
  63. - `presets`
  64. [Here](https://github.com/chenglou/react-motion/blob/9cb90eca20ecf56e77feb816d101a4a9110c7d70/src/Types.js)'s the well-annotated public [Flow type](http://flowtype.org) definition file (you don't have to use Flow with React-motion, but the types help document the API below).
  65. P.S. using TypeScript? [Here](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-motion/index.d.ts) are the React-motion TypeScript definitions!
  66. ---
  67. ### Helpers
  68. ##### - spring: (val: number, config?: SpringHelperConfig) => OpaqueConfig
  69. 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".
  70. - `val`: the value.
  71. - `config`: optional, for further adjustments. Possible fields:
  72. - `stiffness`: optional, defaults to `170`.
  73. - `damping`: optional, defaults to `26`.
  74. - `precision`: optional, defaults to `0.01`. Specifies both the rounding of the interpolated value and the speed (internal).
  75. It's normal not to feel how stiffness and damping affect your spring; use [Spring Parameters Chooser](http://chenglou.github.io/react-motion/demos/demo5-spring-parameters-chooser) to get a feeling. **Usually**, you'd just use the list of tasteful stiffness/damping presets below.
  76. ##### - Presets for `{stiffness, damping}`
  77. Commonly used spring configurations used like so: `spring(10, presets.wobbly)` or `spring(20, {...presets.gentle, precision: 0.1})`. [See here](https://github.com/chenglou/react-motion/blob/9cb90eca20ecf56e77feb816d101a4a9110c7d70/src/presets.js).
  78. ---
  79. ### &lt;Motion />
  80. #### Usage
  81. ```jsx
  82. <Motion defaultStyle={{x: 0}} style={{x: spring(10)}}>
  83. {interpolatingStyle => <div style={interpolatingStyle} />}
  84. </Motion>
  85. ```
  86. #### Props
  87. ##### - style: Style
  88. 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:
  89. - an `OpaqueConfig` returned from `spring(x)`: interpolate to `x`.
  90. - a `number` `x`: jump to `x`, do not interpolate.
  91. ##### - defaultStyle?: PlainStyle
  92. Optional. The `PlainStyle` type maps to `number`s. 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`)**.
  93. ##### - children: (interpolatedStyle: PlainStyle) => ReactElement
  94. Required **function**.
  95. - `interpolatedStyle`: the interpolated style object passed back to you. E.g. if you gave `style={{x: spring(10), y: spring(20)}}`, you'll receive as `interpolatedStyle`, at a certain time, `{x: 5.2, y: 12.1}`, which you can then apply on your `div` or something else.
  96. - Return: must return **one** React element to render.
  97. ##### - onRest?: () => void
  98. Optional. The callback that fires when the animation comes to a rest.
  99. ---
  100. ### &lt;StaggeredMotion />
  101. Animates a collection of (**fixed length**) items whose values depend on each other, creating a natural, springy, "staggering" effect [like so](http://chenglou.github.io/react-motion/demos/demo1-chat-heads). This is preferred over hard-coding a delay for an array of `Motions` to achieve a similar (but less natural-looking) effect.
  102. #### Usage
  103. ```jsx
  104. <StaggeredMotion
  105. defaultStyles={[{h: 0}, {h: 0}, {h: 0}]}
  106. styles={prevInterpolatedStyles => prevInterpolatedStyles.map((_, i) => {
  107. return i === 0
  108. ? {h: spring(100)}
  109. : {h: spring(prevInterpolatedStyles[i - 1].h)}
  110. })}>
  111. {interpolatingStyles =>
  112. <div>
  113. {interpolatingStyles.map((style, i) =>
  114. <div key={i} style={{border: '1px solid', height: style.h}} />)
  115. }
  116. </div>
  117. }
  118. </StaggeredMotion>
  119. ```
  120. Aka "the current spring's destination value is the interpolating value of the previous spring". Imagine a spring dragging another. Physics, it works!
  121. #### Props
  122. ##### - styles: (previousInterpolatedStyles: ?Array&lt;PlainStyle>) => Array&lt;Style>
  123. Required **function**. **Don't forget the "s"**!
  124. - `previousInterpolatedStyles`: the previously interpolating (array of) styles (`undefined` at first render, unless `defaultStyles` is provided).
  125. - Return: must return an array of `Style`s containing the destination values, e.g. `[{x: spring(10)}, {x: spring(20)}]`.
  126. ##### - defaultStyles?: Array&lt;PlainStyle>
  127. Optional. Similar to `Motion`'s `defaultStyle`, but an array of them.
  128. ##### - children: (interpolatedStyles: Array&lt;PlainStyle>) => ReactElement
  129. 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}]`
  130. (No `onRest` for StaggeredMotion because we haven't found a good semantics for it yet. Voice your support in the issues section.)
  131. ---
  132. ### &lt;TransitionMotion />
  133. **Helps you to do mounting and unmounting animation**.
  134. #### Usage
  135. 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.
  136. 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.
  137. 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).
  138. This time, when mapping through the two remaining interpolated styles, you'll produce only two components. `c` is gone for real.
  139. ```jsx
  140. import createReactClass from 'create-react-class';
  141. const Demo = createReactClass({
  142. getInitialState() {
  143. return {
  144. items: [{key: 'a', size: 10}, {key: 'b', size: 20}, {key: 'c', size: 30}],
  145. };
  146. },
  147. componentDidMount() {
  148. this.setState({
  149. items: [{key: 'a', size: 10}, {key: 'b', size: 20}], // remove c.
  150. });
  151. },
  152. willLeave() {
  153. // triggered when c's gone. Keeping c until its width/height reach 0.
  154. return {width: spring(0), height: spring(0)};
  155. },
  156. render() {
  157. return (
  158. <TransitionMotion
  159. willLeave={this.willLeave}
  160. styles={this.state.items.map(item => ({
  161. key: item.key,
  162. style: {width: item.size, height: item.size},
  163. }))}>
  164. {interpolatedStyles =>
  165. // first render: a, b, c. Second: still a, b, c! Only last one's a, b.
  166. <div>
  167. {interpolatedStyles.map(config => {
  168. return <div key={config.key} style={{...config.style, border: '1px solid'}} />
  169. })}
  170. </div>
  171. }
  172. </TransitionMotion>
  173. );
  174. },
  175. });
  176. ```
  177. #### Props
  178. First, two type definitions to ease the comprehension.
  179. - `TransitionStyle`: an object of the format `{key: string, data?: any, style: Style}`.
  180. - `key`: required. The ID that `TransitionMotion` uses to track which configuration is which across renders, even when things are reordered. Typically reused as the component `key` when you map over the interpolated styles.
  181. - `data`: optional. Anything you'd like to carry along. This is so that when the previous section example's `c` disappears, you still get to access `c`'s related data, such as the text to display along with it.
  182. - `style`: required. The actual starting style configuration, similar to what you provide for `Motion`'s `style`. Maps keys to either a number or an `OpaqueConfig` returned by `spring()`.
  183. - `TransitionPlainStyle`: similar to above, except the `style` field's value is of type `PlainStyle`, aka an object that maps to numbers.
  184. ##### - styles: Array&lt;TransitionStyle> | (previousInterpolatedStyles: ?Array&lt;TransitionPlainStyle>) => Array&lt;TransitionStyle>
  185. Required. Accepts either:
  186. - an array of `TransitionStyle` configs, e.g. `[{key: 'a', style: {x: spring(0)}}, {key: 'b', style: {x: spring(10)}}]`.
  187. - a function similar to `StaggeredMotion`, taking the previously interpolating styles (`undefined` at first call, unless `defaultStyles` is provided), and returning the previously mentioned array of configs. __You can do staggered mounting animation with this__.
  188. ##### - defaultStyles?: Array&lt;TransitionPlainStyle>
  189. Optional. Similar to the other components' `defaultStyle`/`defaultStyles`.
  190. ##### - children: (interpolatedStyles: Array&lt;TransitionPlainStyle>) => ReactElement
  191. 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.
  192. ##### - willLeave?: (styleThatLeft: TransitionStyle) => ?Style
  193. Optional. Defaults to `() => null`. **The magic sauce property**.
  194. - `styleThatLeft`: the e.g. `{key: ..., data: ..., style: ...}` object from the `styles` array, identified by `key`, that was present during a previous render, and that is now absent, thus triggering the call to `willLeave`. Note that the style property is exactly what you passed in `styles`, and is not interpolated. For example, if you passed a spring for `x` you will receive an object like `{x: {stiffness, damping, val, precision}}`.
  195. - Return: `null` to indicate you want the `TransitionStyle` gone immediately. A `Style` object to indicate you want to reach transition to the specified value(s) before killing the `TransitionStyle`.
  196. ##### - didLeave?: (styleThatLeft: `{key: string, data?: any}`) => void
  197. Optional. Defaults to `() => {}`.
  198. - `styleThatLeft`: the `{key:..., data:...}` that was removed after the finished transition.
  199. ##### - willEnter?: (styleThatEntered: TransitionStyle) => PlainStyle
  200. Optional. Defaults to `styleThatEntered => stripStyle(styleThatEntered.style)`. Where `stripStyle` turns `{x: spring(10), y: spring(20)}` into `{x: 10, y: 20}`.
  201. - `styleThatEntered`: similar to `willLeave`'s, except the `TransitionStyle` represents the object whose `key` value was absent during the last `render`, and that is now present.
  202. - Return: a `defaultStyle`-like `PlainStyle` configuration, e.g. `{x: 0, y: 0}`, that serves as the starting values of the animation. Under this light, the default provided means "a style config that has the same starting values as the destination values".
  203. **Note** that `willEnter` and `defaultStyles` serve different purposes. `willEnter` only triggers when a previously inexistent `TransitionStyle` inside `styles` comes into the new render.
  204. (No `onRest` for TransitionMotion because we haven't found a good semantics for it yet. Voice your support in the issues section.)
  205. ---
  206. ## FAQ
  207. - How do I set the duration of my animation?
  208. [Hard-coded duration goes against fluid interfaces](https://twitter.com/andy_matuschak/status/566736015188963328). 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](http://chenglou.github.io/react-motion/demos/demo5-spring-parameters-chooser) for you to have a feel of what spring is appropriate, rather than guessing a duration in the dark.
  209. - How do I unmount the `TransitionMotion` container itself?
  210. You don't. Unless you put it in another `TransitionMotion`...
  211. - How do I do staggering/chained animation where items animate in one after another?
  212. See [`StaggeredMotion`](#staggeredmotion-)
  213. - My `ref` doesn't work in the children function.
  214. React string refs won't work:
  215. ```jsx
  216. <Motion style={...}>{currentValue => <div ref="stuff" />}</Motion>
  217. ```
  218. This is how React works. Here's the [callback ref solution](https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute).