1 | <p align="center">
|
2 | <img src="http://nicolasdelfino.com/metro_web_text.png" alt="metro logo" />
|
3 | </p>
|
4 |
|
5 | [![Build Status](https://travis-ci.org/nicolasdelfino/react-metro.svg?branch=master)](https://travis-ci.org/nicolasdelfino/react-metro) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/nicolasdelfino/react-metro/issues)
|
6 |
|
7 | > A tiny configurable wrapper for animating dom elements as they mount or unmount
|
8 |
|
9 | * Optional hooks for binding to mount / unmount sequence complete.
|
10 | * Comes with a simple fade animation but everything can be overriden by providing a custom animationsMap
|
11 |
|
12 | #### Codesandbox demo
|
13 | <a href="https://codesandbox.io/s/w0orz7j5p8" target="_blank">
|
14 | <img src="https://camo.githubusercontent.com/416c7a7433e9d81b4e430b561d92f22ac4f15988/68747470733a2f2f636f646573616e64626f782e696f2f7374617469632f696d672f706c61792d636f646573616e64626f782e737667" alt="edit metro on codesandbox" /></a>
|
15 |
|
16 | #### Medium
|
17 | <a href="https://medium.com/@nicolasdelfino/introducing-react-metro-f766068212d5" target="_blank">Introducing React Metro</a>
|
18 |
|
19 | ### Important notes:
|
20 | 27/09: 1.4.0 introduces BREAKING CHANGES, improvements to the api, see docs below
|
21 |
|
22 | #### Usage
|
23 | Install
|
24 | ```javascript
|
25 | npm install react-metro
|
26 | ```
|
27 | Import
|
28 | ```javascript
|
29 | import Metro from 'react-metro'
|
30 | ```
|
31 | #### Metro.sequence - animate multiple objects:
|
32 |
|
33 | Create a sequence, map it:
|
34 | ```javascript
|
35 | // in method renderMetroComponents:
|
36 |
|
37 | // mount / unmount
|
38 | if(!this.state.showMetroComponents)
|
39 | {
|
40 | return null
|
41 | }
|
42 |
|
43 | const data = ['cat', 'dog']
|
44 |
|
45 | return Metro.sequence(
|
46 | data,
|
47 | animationsMap, // optional
|
48 | defaultAnimation // optional
|
49 | ).map(data => {
|
50 | return (
|
51 | <Metro.animation
|
52 | {...data}
|
53 | wrapperType='div' // optional ul or whatever, defaults to div
|
54 | onClick={this.onClick.bind(this)} // optional
|
55 | enableClickDuringAnimation //optional, boolean (default false)
|
56 | onMount={this.onMountComplete.bind(this)} // optional
|
57 | onUnmount={this.onUnmountComplete.bind(this)}> // optional
|
58 | <YourComponent {...data.content} />
|
59 | </Metro.animation>
|
60 | )
|
61 | })
|
62 | ```
|
63 | & render it:
|
64 | ```javascript
|
65 | <TransitionGroupPlus> // optional arg type="li/div/ul..."
|
66 | { this.renderMetroComponents() }
|
67 | </TransitionGroupPlus>
|
68 | ```
|
69 | #### Metro.container - single node enhancer:
|
70 | ```javascript
|
71 | renderMetroContainer() {
|
72 | if (!this.state.showContainer) {
|
73 | return null;
|
74 | }
|
75 |
|
76 | const props = {
|
77 | wrapperType: "div",
|
78 | enableClickDuringAnimation: true,
|
79 | onMount: this.wrapMount.bind(this),
|
80 | onUnmount: this.wrapUnmount.bind(this)
|
81 | };
|
82 |
|
83 | return Metro.container(
|
84 | <div>...</div>, // base node: pass in text, wrap components
|
85 | containerAnimation, // optional
|
86 | props //optional
|
87 | );
|
88 | }
|
89 | ```
|
90 |
|
91 | #### Customizing animations
|
92 | ```javascript
|
93 | // Override Metro´s default animations settings for each unique item in your items
|
94 | // array, see greensock tweenmax for reference.
|
95 | // The animation settings are combined with the default animation settings, so
|
96 | // you only have to specify the values you want to change.
|
97 | const animationMap = [
|
98 | {
|
99 | in: {
|
100 | time: 3,
|
101 | delay: 0
|
102 | },
|
103 | out: {
|
104 | time: 1.4,
|
105 | delay: 1
|
106 | },
|
107 | willEnter: {
|
108 | from: { opacity: 0, y: 120, x: 30 },
|
109 | to: { opacity: 1, y: 0, x: 0, ease: "easeInOutElastic" }
|
110 | }
|
111 | },
|
112 | {
|
113 | out: {
|
114 | time: 1.4,
|
115 | delay: 0
|
116 | },
|
117 | willEnter: {
|
118 | from: { opacity: 0, y: 120, x: -30 },
|
119 | to: { opacity: 1, y: 0, x: 0, ease: "easeInOutElastic" }
|
120 | }
|
121 | }
|
122 | ];
|
123 |
|
124 | // Metro comes with a simple, fade in / out default. This object passed
|
125 | // in as the third argument in the Metro.sequence overrides the default settings.
|
126 | // The override settings are combined with the built in defaults, so you only
|
127 | // have to specify the values you want to change.
|
128 | const defaultAnimationOverride = {
|
129 | animation: {
|
130 | out: {
|
131 | time: 0.5,
|
132 | delay: 0
|
133 | },
|
134 | in: {
|
135 | time: 1,
|
136 | delay: 0
|
137 | },
|
138 | willEnter: {
|
139 | from: { opacity: 0, y: 50 },
|
140 | to: { opacity: 1, y: 0, ease: "easeInOutQuad" }
|
141 | },
|
142 | willLeave: {
|
143 | from: {
|
144 | opacity: 1,
|
145 | y: 0
|
146 | },
|
147 | to: { opacity: 0, y: 50, ease: "easeInOutQuad" }
|
148 | }
|
149 | }
|
150 | };
|
151 | ```
|
152 | #### Methods
|
153 | ```javascript
|
154 | wrapperType // dom element, defaults to div
|
155 | onClick // receives props (original array data), array index and animating
|
156 | enableClickDuringAnimation // boolean, defaults to false
|
157 | onMount // fires when the mount sequence completes
|
158 | onUnmount // fires when the unmount sequence completes
|
159 | ```
|
160 | #### Advanced usage
|
161 | The real power of Metro shines through it's use of dynamic animationMaps.
|
162 |
|
163 | <a href="https://codesandbox.io/s/w0orz7j5p8" target="_blank">The second demo</a> demonstrates the concept of dynamic sequences. This is achieved by altering the sequence´s animationMap on user interaction.
|
164 |
|
165 | We define an animatonMap to achieve the delayed entrance effect we want. Since the active animationMap is stored in our wrapper component´s local state we can replace our initial map on user interaction, thus making the animation interactive.
|
166 |
|
167 | Even though the developer has total control of an animation through the use of custom animationMaps, we created a helper method called Metro.generateFocusMap for cases where you want to accentuate a specific item within your sequence without having to write logic.
|
168 |
|
169 | These presets - today a total of 4: verticalDelayed, dominoForwards, dominoBackwards, dominoMulti, is something that you as a developer are more than welcome to contribute to. Ideas for upcoming presets are stuff like 'checkerBoard' / 'wave' / 'circular' etc...
|
170 |
|
171 | Each preset should try to incorporate the focus-first logic as they are intended to accentuate a clicked component.
|
172 | Current api for using the method is:
|
173 | ```javascript
|
174 | const domino = Metro.generateFocusMap(
|
175 | index, //focus - index of clicked component
|
176 | 6, // columns
|
177 | this.state.data.length, // length of sequence
|
178 | this.state.preset // preset - dynamic in state or put directly as string 'dominoMulti'
|
179 | duration // optional (default 1 second)
|
180 | )
|
181 | this.setState({animationMap: domino}) // -> do unmount logic...
|
182 | ```
|
183 |
|
184 | #### Contribute
|
185 |
|
186 | ##### PRs
|
187 | PRs are welcomed, to contribute make sure that:
|
188 | * Branch name references issue number if it adresses a feature / bug fix.
|
189 | * Branch has already been [synced with the upstream repo](https://help.github.com/articles/syncing-a-fork/) and any merge-conflicts have been resolved.
|
190 | * Install eslint and prettier to avoid lint issues while developing
|
191 | * Use <a href="https://github.com/semantic-release/semantic-release">semantic release guidelines</a> when commiting
|
192 |
|
193 | ##### Contributors
|
194 | <img src="https://avatars3.githubusercontent.com/u/26581738?v=4&s=400" width="70px;"/><br /><a href="https://github.com/emilpalsson"><sub>Emil Pålsson</sub></a>
|
195 |
|
196 | ##### Issues
|
197 | Please be descriptive
|
198 |
|
199 | #### Disclaimer: GSAP tools are subject to their own license (www.greensock.com)
|