├── .gitignore
├── .npmignore
├── README.md
├── bower.json
├── build
├── canvas.js
├── demo.js
└── fps.js
├── examples
├── common
│ └── examples.css
├── demo
│ ├── Demo.js
│ ├── DemoCanvas.js
│ ├── DemoCanvasNoState.js
│ ├── app.js
│ ├── canvas.html
│ ├── canvas.js
│ └── index.html
└── fps
│ ├── app.js
│ └── index.html
├── gulpfile.js
├── lib
├── Animate.js
├── Easing.js
├── Loop.js
└── ReactStateAnimation.js
├── package.json
├── src
├── Animate.js
├── Loop.js
└── ReactStateAnimation.js
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .idea
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | build
2 | src
3 | node_modules
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-state-animation
2 |
3 | react-state-animation provides a capability to update React component's state value by requestAnimationFrame with a simple APIs that builds on d3-ease. The file size is just **4KB** (minified).
4 |
5 | This works with regular [React](http://facebook.github.io/react/) component and [React Canvas](https://github.com/Flipboard/react-canvas)
6 |
7 | ## Installation
8 | `npm install react-state-animation --save`
9 | Include the module by CommonJS way
10 | `import ReactStateAnimation from 'react-state-animation'` or `var ReactStateAnimation = require('react-state-animation');`
11 |
12 | This will require ES5 modules converted by babel. ES6 sources are in /src and converted ES5 modules are located in /lib.
13 |
14 | ##Demo
15 | [http://tejitak.github.io/react-state-animation/examples/demo/](http://tejitak.github.io/react-state-animation/examples/demo/)
16 |
17 | ## API
18 |
19 | - linearIn(*stateProp*, *endStateValue*, *duration*)
20 | - linearOut(*stateProp*, *endStateValue*, *duration*)
21 | - linearInOut(*stateProp*, *endStateValue*, *duration*)
22 | - quadIn(*stateProp*, *endStateValue*, *duration*)
23 | - quadOut(*stateProp*, *endStateValue*, *duration*)
24 | - quadInOut(*stateProp*, *endStateValue*, *duration*)
25 | - cubicIn(*stateProp*, *endStateValue*, *duration*)
26 | - cubicOut(*stateProp*, *endStateValue*, *duration*)
27 | - cubicInOut(*stateProp*, *endStateValue*, *duration*)
28 | - polyIn(*stateProp*, *endStateValue*, *duration*)
29 | - polyOut(*stateProp*, *endStateValue*, *duration*)
30 | - polyInOut(*stateProp*, *endStateValue*, *duration*)
31 | - sinIn(*stateProp*, *endStateValue*, *duration*)
32 | - sinOut(*stateProp*, *endStateValue*, *duration*)
33 | - sinInOut(*stateProp*, *endStateValue*, *duration*)
34 | - expIn(*stateProp*, *endStateValue*, *duration*)
35 | - expOut(*stateProp*, *endStateValue*, *duration*)
36 | - expInOut(*stateProp*, *endStateValue*, *duration*)
37 | - circleIn(*stateProp*, *endStateValue*, *duration*)
38 | - circleOut(*stateProp*, *endStateValue*, *duration*)
39 | - circleInOut(*stateProp*, *endStateValue*, *duration*)
40 | - bounceIn(*stateProp*, *endStateValue*, *duration*)
41 | - bounceOut(*stateProp*, *endStateValue*, *duration*)
42 | - bounceInOut(*stateProp*, *endStateValue*, *duration*)
43 | - backIn(*stateProp*, *endStateValue*, *duration*)
44 | - backOut(*stateProp*, *endStateValue*, *duration*)
45 | - backInOut(*stateProp*, *endStateValue*, *duration*)
46 | - elasticIn(*stateProp*, *endStateValue*, *duration*)
47 | - elasticOut(*stateProp*, *endStateValue*, *duration*)
48 | - elasticInOut(*stateProp*, *endStateValue*, *duration*)
49 |
50 | The above API returns Promise, so you can chain additinal processes by using then.
51 |
52 | ##Usage
53 | ### Example 1. Use outside of component
54 | ```js:app.js
55 | var yourComponent = React.render(
56 | ,
57 | document.getElementById('demo')
58 | )
59 | var reactStateAnimation = new ReactStateAnimation(yourComponent)
60 | // your component's state 'x' will be updated to 350 with linear order in 1 sec, then alpha will be 0 on end of moving
61 | reactStateAnimation.linearInOut('x', 350/*end value*/, 1000/*duration(ms)*/).then(() => reactStateAnimation.linearInOut('alpha', 0, 400))
62 | ```
63 |
64 | ### Example 2. Linear Move in React Component
65 | Set any state (e.g. 'x') associated with position left style
66 | ```js:Demo.js
67 | import React from 'react'
68 | import ReactStateAnimation from 'react-state-animation'
69 |
70 | export default class Demo extends React.Component {
71 | constructor(props) {
72 | super(props)
73 | this.state = {
74 | x: 0
75 | }
76 | // react state animation wrapper
77 | this._animate = new ReactStateAnimation(this)
78 | }
79 |
80 | start() {
81 | // start animation
82 | this._animate.linearInOut('x', 350/*end value*/, 1000/*duration(ms)*/)
83 | }
84 |
85 | stop() {
86 | this._animate.stop()
87 | }
88 |
89 | getStyle() {
90 | return {
91 | position: 'absolute',
92 | backgroundColor: "#009688",
93 | top: 0,
94 | left: this.state.x + "px",
95 | width: this.props.width,
96 | height: this.props.height
97 | }
98 | }
99 |
100 | render() {
101 | return (
102 |
103 | )
104 | }
105 | }
106 |
107 | Demo.defaultProps = {
108 | width: 50,
109 | height: 50
110 | }
111 | ```
112 |
113 | ### Example 3. Linear Move in React Canvas
114 | Set any state (e.g. 'x') associated with position left style
115 | ```js:DemoCanvas.js
116 | import React from 'react'
117 | import ReactCanvas from 'react-canvas'
118 | import ReactStateAnimation from 'react-state-animation'
119 |
120 | var Surface = ReactCanvas.Surface
121 | var Group = ReactCanvas.Group
122 | var Layer = ReactCanvas.Layer
123 |
124 | export default class DemoCanvas extends React.Component {
125 | constructor(props) {
126 | super(props)
127 | this.state = {
128 | x: 0
129 | }
130 | // react state animation wrapper
131 | this._animate = new ReactStateAnimation(this)
132 | }
133 |
134 | start() {
135 | // start animation
136 | this._animate.linearInOut('x', 350/*end value*/, 1000/*duration*/)
137 | }
138 |
139 | stop() {
140 | this._animate.stop()
141 | }
142 |
143 | getGroupStyle() {
144 | return {
145 | position: 'absolute',
146 | backgroundColor: "#f4f4f4",
147 | top: 0,
148 | left: 0,
149 | width: this.props.canvasWidth,
150 | height: this.props.canvasHeight
151 | }
152 | }
153 |
154 | getStyle() {
155 | return {
156 | position: 'absolute',
157 | backgroundColor: "#009688",
158 | top: 0,
159 | left: this.state.x,
160 | width: this.props.width,
161 | height: this.props.height
162 | }
163 | }
164 |
165 | render() {
166 | return (
167 |
168 |
169 |
170 |
171 |
172 | )
173 | }
174 | }
175 |
176 | DemoCanvas.defaultProps = {
177 | canvasWidth: 400,
178 | canvasHeight: 50,
179 | width: 50,
180 | height: 50
181 | }
182 | ```
183 |
184 | ### Example 4. Multiple states in ReactART
185 | Set any state (e.g. 'x') associated with position left style
186 | ```js:DemoCanvas.js
187 |
188 | import React from 'react'
189 | import ReactART from 'react-art'
190 | import Circle from 'react-art/lib/Circle.art.js'
191 | import ReactStateAnimation from 'react-state-animation'
192 |
193 | var Surface = ReactCanvas.Surface
194 |
195 | export default class DemoCanvas extends React.Component {
196 | constructor(props) {
197 | super(props)
198 | this.state = {
199 | x: props.position.x,
200 | y: props.position.y,
201 | radius: props.radius
202 | }
203 | // react state animation wrapper
204 | this._animate = new ReactStateAnimation(this)
205 | }
206 |
207 | _Floating() {
208 | // pass an array to the manimate method with the states, to be animated
209 | this._animate.manimate([
210 | /* state: 'theNameOfTheState', target: endValue */
211 | {state: 'x', target: this.props.position.x-15},
212 | {state: 'radius', target: this.props.radius+4}
213 | ], 800, 'elasticInOut')
214 | .then(() => this._animate.manimate([
215 | {state: 'x', target: this.props.position.x},
216 | {state: 'radius', target: this.props.radius-2}
217 | ], 800, 'elasticInOut'))
218 | .then(() => this._Floating());
219 | }
220 |
221 | render() {
222 | return (
223 |
224 |
225 |
226 | )
227 | }
228 | }
229 |
230 | DemoCanvas.defaultProps = {
231 | canvasWidth: 400,
232 | canvasHeight: 300,
233 | radius: 30,
234 | position: {
235 | x: 50,
236 | y: 50
237 | }
238 | }
239 | ```
240 |
241 | ## Note
242 | React setState is now asynchronously called as a batch. So, using regular instance properties instaed of state seems faste especially for React Canvas.
243 |
244 | Please check the [demo for canvas performance between React Canvas with setState (asynchronous and batch) and without setStates](http://tejitak.github.io/react-state-animation/examples/demo/canvas.html)
245 |
246 |
247 | ## Development
248 |
249 | 1. Run "npm install"
250 | 2. Run "gulp"
251 | 3. Access to "http://localhost:8080/html/"
252 |
253 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-state-animation",
3 | "main": "index.js",
4 | "version": "0.0.1",
5 | "homepage": "https://github.com/tejitak/react-state-animation",
6 | "authors": [
7 | "tejitak"
8 | ],
9 | "description": "Simple animations with React state",
10 | "keywords": [
11 | "react",
12 | "animation",
13 | "tween",
14 | "transition",
15 | "state",
16 | "easing"
17 | ],
18 | "license": "MIT",
19 | "ignore": [
20 | "**/.*",
21 | "examples",
22 | "index.js",
23 | "node_modules",
24 | "bower_components",
25 | "test",
26 | "tests"
27 | ]
28 | }
--------------------------------------------------------------------------------
/examples/common/examples.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | margin: 0;
3 | font-family: 'Roboto', sans-serif;
4 | color: #101010;
5 | }
6 |
7 | h1, h2, h3 {
8 | color: #333;
9 | font-size: 33px;
10 | font-weight: normal;
11 | }
12 |
13 | h2 {
14 | display: none;
15 | font-size: 33px;
16 | }
17 |
18 | h3 {
19 | border-bottom: 3px solid #eee;
20 | font-size: 18px;
21 | padding: 5px 0;
22 | margin: 20px 0 10px;
23 | font-weight: bold;
24 | }
25 |
26 | h4 {
27 | margin: 12px 0;
28 | }
29 |
30 | header {
31 | background-color: #009688;
32 | width: 100%;
33 | box-shadow: 0 1px 5px rgba(0,0,0,.3);
34 | color: #fff;
35 | font-size: 2em;
36 | font-weight: bold;
37 | padding: 20px 0;
38 | text-align: center;
39 | }
40 |
41 | footer {
42 | background-color: #009688;
43 | width: 100%;
44 | box-shadow: 0 1px 5px rgba(0,0,0,.3);
45 | color: #fff;
46 | text-align: center;
47 | padding: 8px 0;
48 | margin-top: 12px;
49 | }
50 |
51 | section {
52 | margin: 8px 0;
53 | }
54 |
55 | .wrap {
56 | padding: 20px 50px;
57 | }
58 |
59 | .description {
60 | text-align: center;
61 | margin: 20px;
62 | }
63 |
64 | .social_container {
65 | width: 300px;
66 | margin: 4px auto;
67 | text-align: center;
68 | }
69 |
70 | .social_container .social_item{
71 | display: inline-block;
72 | padding: 4px 20px
73 | }
74 |
75 | @media (min-width: 481px) {
76 | .social_container {
77 | width: 100%;
78 | }
79 | }
80 |
81 | .separator {
82 | margin: 30px 0px;
83 | height: 3px;
84 | background: #eaeaea;
85 | border-radius: 2px;
86 | }
87 |
88 | .container {
89 | position: relative;
90 | width: 400px;
91 | height: 50px;
92 | background-color: #f4f4f4;
93 | margin-bottom: 10px;
94 | }
95 |
96 | .floatContainer {
97 | height: 110px;
98 | width: 540px;
99 | margin-top: 10px;
100 | }
101 |
102 | .floatLeftItem {
103 | float: left;
104 | width: 90px;
105 | height: 100px;
106 | padding: 0px 20px 0 0;
107 | }
108 |
109 | .floatRightItem {
110 | float: left;
111 | width: 400px;
112 | height: 100px;
113 | }
--------------------------------------------------------------------------------
/examples/demo/Demo.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactStateAnimation from 'react-state-animation'
3 |
4 | export default class Demo extends React.Component {
5 | constructor(props) {
6 | super(props)
7 | // initialize state
8 | this.state = {
9 | x: 0,
10 | alpha: 1
11 | }
12 | // this.x = 0
13 | // this.alpha = 1
14 | // react state animation wrapper
15 | this._animate = new ReactStateAnimation(this)
16 | }
17 |
18 | start() {
19 | this._animate[this.props.easing]('x', 350/*end value*/, 1000/*duration(ms)*/)
20 | .then(() => this._animate[this.props.easing]('alpha', 0, 500))
21 | }
22 |
23 | stop() {
24 | this._animate.stop()
25 | }
26 |
27 | getStyle() {
28 | return {
29 | position: 'absolute',
30 | backgroundColor: "#009688",
31 | top: 0,
32 | // opacity: this.alpha,
33 | // left: this.x + "px",
34 | opacity: this.state.alpha,
35 | left: this.state.x + "px",
36 | width: this.props.width,
37 | height: this.props.height
38 | }
39 | }
40 |
41 | render() {
42 | return (
43 |
44 | )
45 | }
46 | }
47 |
48 | Demo.defaultProps = {
49 | width: 50,
50 | height: 50,
51 | easing: ''
52 | }
--------------------------------------------------------------------------------
/examples/demo/DemoCanvas.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactCanvas from 'react-canvas'
3 | import ReactStateAnimation from 'react-state-animation'
4 |
5 | var Surface = ReactCanvas.Surface
6 | var Group = ReactCanvas.Group
7 | var Layer = ReactCanvas.Layer
8 |
9 | export default class DemoCanvas extends React.Component {
10 | constructor(props) {
11 | super(props)
12 | // initialize state
13 | this.state = {
14 | x: 0,
15 | alpha: 1
16 | }
17 | // react state animation wrapper
18 | this._animate = new ReactStateAnimation(this)
19 | }
20 |
21 | start() {
22 | this._animate[this.props.easing]('x', 350/*end value*/, 1000/*duration*/)
23 | .then(() => this._animate[this.props.easing]('alpha', 0, 400))
24 | }
25 |
26 | stop() {
27 | this._animate.stop()
28 | }
29 |
30 | getGroupStyle() {
31 | return {
32 | position: 'absolute',
33 | backgroundColor: "#f4f4f4",
34 | top: 0,
35 | left: 0,
36 | width: this.props.canvasWidth,
37 | height: this.props.canvasHeight
38 | }
39 | }
40 |
41 | getStyle() {
42 | return {
43 | position: 'absolute',
44 | backgroundColor: "#009688",
45 | top: 0,
46 | alpha: this.state.alpha,
47 | left: this.state.x,
48 | width: this.props.width,
49 | height: this.props.height
50 | }
51 | }
52 |
53 | render() {
54 | return (
55 |
56 |
57 |
58 |
59 |
60 | )
61 | }
62 | }
63 |
64 | DemoCanvas.defaultProps = {
65 | canvasWidth: 400,
66 | canvasHeight: 50,
67 | width: 50,
68 | height: 50,
69 | easing: ''
70 | }
--------------------------------------------------------------------------------
/examples/demo/DemoCanvasNoState.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import DemoCanvas from './DemoCanvas'
3 |
4 | export default class DemoCanvasNoState extends DemoCanvas {
5 | constructor(props) {
6 | super(props)
7 | // initialize state
8 | this.state = {}
9 | // replace state to instance props
10 | this.x = 0
11 | this.alpha = 1
12 | }
13 |
14 | getStyle() {
15 | return {
16 | position: 'absolute',
17 | backgroundColor: "#009688",
18 | top: 0,
19 | // replace state to instance props
20 | alpha: this.alpha,
21 | left: this.x,
22 | width: this.props.width,
23 | height: this.props.height
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/examples/demo/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Demo from './Demo'
3 | import DemoCanvas from './DemoCanvas'
4 |
5 | var d = document,
6 | components = [],
7 | easingTypes = ['linear', 'easeInQuad', 'easeInCubic', 'easeOutCubic', 'easeInOutCubic']
8 |
9 | // set up DOM for each easing types
10 | easingTypes.forEach((easing, i) => {
11 | var div = d.createElement("DIV"),
12 | html = ['', easing, " ",
13 | "reactStateAnimation." + easing + "('x', 350/*end value*/, 1000/*duration(ms)*/).then(() => reactStateAnimation." + easing + "('alpha', 0, 400))
",
14 | '',
15 | '
React Component React Canvas ',
16 | '
',
17 | '
']
18 | div.innerHTML = html.join("")
19 | // render React component
20 | components.push(React.render(
21 | ,
22 | div.querySelector('.container')
23 | ))
24 | // render React Canvas
25 | components.push(React.render(
26 | ,
27 | div.querySelector('.canvasContainer')
28 | ))
29 | d.getElementById('demo').appendChild(div)
30 | })
31 |
32 | // action buttons
33 | var start = () => {
34 | components.forEach(c => {
35 | c.setState({x: 0, alpha: 1}, () => {
36 | c.start()
37 | })
38 | })
39 | }
40 |
41 | var resume = () => {
42 | components.forEach(c => {
43 | c.start()
44 | })
45 | }
46 |
47 | var stop = () => {
48 | components.forEach(c => {
49 | c.stop()
50 | })
51 | }
52 |
53 | d.getElementById('startBtn1').addEventListener('click', start)
54 | d.getElementById('startBtn2').addEventListener('click', start)
55 | d.getElementById('resumeBtn1').addEventListener('click', resume)
56 | d.getElementById('resumeBtn2').addEventListener('click', resume)
57 | d.getElementById('stopBtn1').addEventListener('click', stop)
58 | d.getElementById('stopBtn2').addEventListener('click', stop)
--------------------------------------------------------------------------------
/examples/demo/canvas.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ReactStateAnimation Demo for canvas setState performance
7 |
8 |
9 |
10 |
11 | react-state-animation for canvas performance
12 |
13 |
14 |
15 |
react-state-animation provides a capability to update React component's state by requestAnimationFrame with a simple APIs.
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | This demo is for performance check between React Canvas with setState (asynchronous and batch) and without setStates. Press start to check animation
27 |
28 |
29 |
30 | Start
31 | Stop
32 | Resume
33 |
34 |
35 |
36 |
37 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/examples/demo/canvas.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Demo from './Demo'
3 | import DemoCanvas from './DemoCanvas'
4 | import DemoCanvasNoState from './DemoCanvasNoState'
5 |
6 | var d = document,
7 | components = [],
8 | easingTypes = ['linear', 'easeInQuad', 'easeInCubic', 'easeOutCubic', 'easeInOutCubic']
9 |
10 | // set up DOM for each easing types
11 | easingTypes.forEach((easing, i) => {
12 | var div = d.createElement("DIV"),
13 | html = ['', easing, " ",
14 | "reactStateAnimation." + easing + "('x', 350/*end value*/, 1000/*duration(ms)*/).then(() => reactStateAnimation." + easing + "('alpha', 0, 400))
",
15 | '',
16 | '
Canvas w/ setState Canvas w/o setState ',
17 | '
',
18 | '
']
19 | div.innerHTML = html.join("")
20 | // render React component
21 | components.push(React.render(
22 | ,
23 | div.querySelector('.with')
24 | ))
25 | // render React Canvas
26 | components.push(React.render(
27 | ,
28 | div.querySelector('.without')
29 | ))
30 | d.getElementById('demo').appendChild(div)
31 | })
32 |
33 | // action buttons
34 | d.getElementById('startBtn').addEventListener('click', () => {
35 | components.forEach(c => {
36 | if(c.state.x) {
37 | c.setState({x: 0, alpha: 1}, () => {
38 | c.start()
39 | })
40 | }else{
41 | c.x = 0
42 | c.alpha = 1
43 | c.start()
44 | }
45 | })
46 | })
47 |
48 | d.getElementById('resumeBtn').addEventListener('click', () => {
49 | components.forEach(c => {
50 | c.start()
51 | })
52 | })
53 |
54 | d.getElementById('stopBtn').addEventListener('click', () => {
55 | components.forEach(c => {
56 | c.stop()
57 | })
58 | })
59 |
60 |
61 |
--------------------------------------------------------------------------------
/examples/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ReactStateAnimation Demo
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
react-state-animation provides a capability to update React component's state by requestAnimationFrame with a simple APIs. The file size is just 4KB (minified).
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | The following React components have state {x: 0} as an initial value. And the state is used in style. Press start to check animation
27 |
28 |
29 |
30 | Start
31 | Stop
32 | Resume
33 |
34 |
35 |
36 |
37 |
38 | Start
39 | Stop
40 | Resume
41 |
42 |
43 |
44 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/examples/fps/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactStateAnimation from 'react-state-animation'
3 | import Demo from '../demo/Demo'
4 | import DemoCanvas from '../demo/DemoCanvas'
5 |
6 | var d = document,
7 | demo = React.render(
8 | ,
9 | d.getElementById('demo')
10 | ),
11 | anim = new ReactStateAnimation(demo),
12 | demoDuration = 1000
13 |
14 | anim.onProcess = () => {
15 | stats.update();
16 | }
17 |
18 | d.getElementById('startDemoBtn').addEventListener('click', () => {
19 | // demo.setState({x: 0}, () => {
20 | // anim.linear('x', 350/*end value*/, demoDuration)
21 | // })
22 | demo.x = 0;
23 | anim.linear('x', 350/*end value*/, demoDuration)
24 | })
25 |
26 | d.getElementById('durationDemoInput').addEventListener('change', (e) => {
27 | demoDuration = e.target.value - 0
28 | })
29 |
30 | var demoCanvas = React.render(
31 | ,
32 | d.getElementById('demoCanvas')
33 | ),
34 | animCanvas = new ReactStateAnimation(demoCanvas),
35 | demoCanvasDuration = 1000
36 |
37 | animCanvas.onProcess = () => {
38 | stats.update();
39 | }
40 |
41 | d.getElementById('startDemoCanvasBtn').addEventListener('click', () => {
42 | demoCanvas.x = 0;
43 | animCanvas.linear('x', 350/*end value*/, demoCanvasDuration)
44 | // demoCanvas.setState({x: 0}, () => {
45 | // animCanvas.linear('x', 350/*end value*/, demoCanvasDuration)
46 | // })
47 | })
48 |
49 | d.getElementById('durationDemoCanvasInput').addEventListener('change', (e) => {
50 | demoCanvasDuration = e.target.value - 0
51 | })
--------------------------------------------------------------------------------
/examples/fps/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ReactStateAnimation Demo
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | React Component
15 |
16 |
Duration:
17 |
Start
18 |
19 |
20 |
21 |
22 |
23 | React Canvas
24 |
25 |
Duration:
26 |
Start
27 |
28 |
29 |
30 |
31 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var del = require('del');
3 | var argv = require('yargs').argv;
4 | var gulpif = require('gulp-if');
5 | var connect = require('gulp-connect');
6 | var uglify = require('gulp-uglify');
7 | var babel = require('gulp-babel');
8 | var webpack = require('gulp-webpack');
9 | var webpackConfig = require('./webpack.config.js');
10 |
11 | var port = process.env.PORT || 8080;
12 | var reloadPort = process.env.RELOAD_PORT || 35729;
13 |
14 | gulp.task('clean', function () {
15 | return del.sync(['lib', 'build']);
16 | });
17 |
18 | // convert to es5 from es6 src modules with babel
19 | gulp.task('lib', function (cb) {
20 | return gulp.src('./src/**/*.js')
21 | .pipe(babel())
22 | .pipe(gulp.dest('lib/'));
23 | });
24 |
25 | // build for examples with webpack
26 | gulp.task('build', ['lib'], function () {
27 | return gulp.src(webpackConfig.entry.demo[0])
28 | .pipe(webpack(webpackConfig))
29 | .pipe(gulpif(argv.production, uglify()))
30 | .pipe(gulp.dest('build/'));
31 | });
32 |
33 | gulp.task('serve', function () {
34 | connect.server({
35 | port: port,
36 | livereload: {
37 | port: reloadPort
38 | }
39 | });
40 | });
41 |
42 | gulp.task('reload-js', function () {
43 | return gulp.src('./build/*.js')
44 | .pipe(connect.reload());
45 | });
46 |
47 | gulp.task('watch', function () {
48 | gulp.watch(['./build/*.js'], ['reload-js']);
49 | });
50 |
51 | gulp.task('default', ['clean', 'lib', 'build', 'serve', 'watch']);
52 |
--------------------------------------------------------------------------------
/lib/Animate.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
4 |
5 | var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
6 |
7 | var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
8 |
9 | var Loop = _interopRequire(require("./Loop"));
10 |
11 | var ease = require("d3-ease").ease;
12 |
13 | var eases = ["linear-in", "linear-out", "linear-in-out", "quad-in", "quad-out", "quad-in-out", "cubic-in", "cubic-out", "cubic-in-out", "poly-in", "poly-out", "poly-in-out", "sin-in", "sin-out", "sin-in-out", "exp-in", "exp-out", "exp-in-out", "circle-in", "circle-out", "circle-in-out", "bounce-in", "bounce-out", "bounce-in-out", "back-in", "back-out", "back-in-out", "elastic-in", "elastic-out", "elastic-in-out"],
14 | Easing = {};
15 |
16 | /**
17 | * React state animation wrapper
18 | * - update state value by requestAnimationFrame loop
19 | */
20 |
21 | var Animate = (function () {
22 | function Animate(component) {
23 | var _this = this;
24 |
25 | _classCallCheck(this, Animate);
26 |
27 | this._component = component;
28 |
29 | // generate an interface function for each ease.
30 | eases.forEach(function (e) {
31 | // convert to camelCase
32 | var easeName = e.replace(/-([a-z])/g, function (g) {
33 | return g[1].toUpperCase();
34 | });
35 |
36 | // add instance methods dynamically
37 | _this[easeName] = function (prop, end, duration) {
38 | return this.animate(prop, end, duration, easeName);
39 | };
40 |
41 | Easing[easeName] = ease(e);
42 | });
43 | }
44 |
45 | _createClass(Animate, {
46 | _getStateValue: {
47 |
48 | /**
49 | * Get state value
50 | * if the prop is not in state regular property
51 | */
52 |
53 | value: function _getStateValue(prop) {
54 | var c = this._component,
55 | v = c.state && c.state[prop];
56 | return v === undefined ? c[prop] : v;
57 | }
58 | },
59 | _updateStateValue: {
60 |
61 | /**
62 | * Set value to state
63 | * if the prop is not in state, set value to regular property with force update
64 | */
65 |
66 | value: function _updateStateValue(prop, v) {
67 | var _this = this;
68 |
69 | return new Promise(function (resolve, reject) {
70 | var c = _this._component;
71 | if (c.state && c.state[prop] !== undefined) {
72 | var state = {};
73 | state[prop] = v;
74 | c.setState(state, resolve);
75 | } else {
76 | c[prop] = v;
77 | c.forceUpdate();
78 | resolve();
79 | }
80 | });
81 | }
82 | },
83 | _updateStateMap: {
84 |
85 | /**
86 | * Updates multiple properties within
87 | * @param prop {Array} array of targeted states= {state: {string}, target: {number}}
88 | * @param values {Array} array of values to be set
89 | * @returns {Promise}
90 | */
91 |
92 | value: function _updateStateMap(prop, values) {
93 | var _this = this;
94 |
95 | return new Promise(function (resolve, reject) {
96 | var c = _this._component,
97 | state = {};
98 | // build up changed state
99 | for (var i = 0; i < prop.length; i++) {
100 | state[prop[i].state] = values[i];
101 | }
102 | c.setState(state, resolve);
103 | });
104 | }
105 | },
106 | _start: {
107 | value: function _start(loopCallback) {
108 | this._loop = new Loop(loopCallback);
109 | this._loop.start();
110 | }
111 | },
112 | animate: {
113 | value: function animate(prop, end, duration, easing) {
114 | var _this = this;
115 |
116 | if (!Easing[easing]) {
117 | console.log("Specified easing does not exist: " + easing);
118 | return;
119 | }
120 | return new Promise(function (resolve, reject) {
121 | var begin = _this._getStateValue(prop);
122 | _this._start(function () {
123 | return _this._anim(prop, begin, end, duration, easing, resolve);
124 | });
125 | });
126 | }
127 | },
128 | manimate: {
129 | value: function manimate(prop, duration, easing) {
130 | var _this = this;
131 |
132 | if (!Easing[easing]) {
133 | console.log("Specified easing does not exist: " + easing);
134 | return;
135 | }
136 | return new Promise(function (resolve, reject) {
137 | // gather array begin States
138 | var begins = [],
139 | ends = [];
140 | for (var i = 0; i < prop.length; i++) {
141 | var b = _this._getStateValue(prop[i].state);
142 | var e = prop[i].target;
143 | begins.push(b);
144 | ends.push(e);
145 | }
146 | // start multi-anim
147 | _this._start(function () {
148 | return _this._multianim(prop, begins, ends, duration, easing, resolve);
149 | });
150 | });
151 | }
152 | },
153 | onProcess: {
154 |
155 | // for override on each loop
156 |
157 | value: function onProcess(prop, value, progress) {}
158 | },
159 | _anim: {
160 |
161 | /**
162 | * Start animation
163 | * - prop is a react state property
164 | * - end is a goal value of the state
165 | */
166 |
167 | value: function _anim(prop, begin, end, duration, easing, resolve) {
168 | if (!this._loop) {
169 | resolve();
170 | return false;
171 | }
172 | var progress = Easing[easing](this._loop.timeDiff() / duration),
173 | distance = Math.abs(begin - end),
174 | diff = progress * distance,
175 | operator = begin > end ? -1 : 1,
176 | value = begin + diff * operator;
177 | this.onProcess(prop, value, progress);
178 | if (progress < 1) {
179 | // return promise to keep loop
180 | return this._updateStateValue(prop, value);
181 | } else {
182 | this.stop();
183 | this._updateStateValue(prop, end).then(function () {
184 | resolve();
185 | });
186 | return false;
187 | }
188 | }
189 | },
190 | _multianim: {
191 | value: function _multianim(prop, begins, ends, duration, easing, resolve) {
192 | if (!this._loop) {
193 | resolve();
194 | return false;
195 | }
196 | var progress = Easing[easing](this._loop.timeDiff() / duration),
197 | newValues = [];
198 |
199 | // step through all states
200 | for (var i = 0; i < prop.length; i++) {
201 | var begin = begins[i],
202 | end = ends[i],
203 | p = prop[i].state,
204 | distance = Math.abs(begin - end),
205 | diff = progress * distance,
206 | operator = begin > end ? -1 : 1,
207 | value = begin + diff * operator;
208 |
209 | this.onProcess(p, value, progress);
210 |
211 | newValues.push(value);
212 | }
213 |
214 | if (progress < 1) {
215 | return this._updateStateMap(prop, newValues);
216 | } else {
217 | this.stop();
218 | this._updateStateMap(prop, ends).then(function () {
219 | resolve();
220 | });
221 | return false;
222 | }
223 | }
224 | },
225 | stop: {
226 | value: function stop() {
227 | if (this._loop) {
228 | this._loop.end();
229 | this._loop = null;
230 | }
231 | return this;
232 | }
233 | }
234 | });
235 |
236 | return Animate;
237 | })();
238 |
239 | module.exports = Animate;
--------------------------------------------------------------------------------
/lib/Easing.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
4 |
5 | var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
6 |
7 | var Easing = (function () {
8 | function Easing() {
9 | _classCallCheck(this, Easing);
10 | }
11 |
12 | _createClass(Easing, {
13 | linear: {
14 | value: function linear(t) {
15 | return t;
16 | }
17 | },
18 | easeInQuad: {
19 | value: function easeInQuad(t) {
20 | return Math.pow(t, 2);
21 | }
22 | },
23 | easeInCubic: {
24 | value: function easeInCubic(t) {
25 | return t * t * t;
26 | }
27 | },
28 | easeOutCubic: {
29 | value: function easeOutCubic(t) {
30 | return --t * t * t + 1;
31 | }
32 | },
33 | easeInOutCubic: {
34 | value: function easeInOutCubic(t) {
35 | return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
36 | }
37 | }
38 | });
39 |
40 | return Easing;
41 | })();
42 |
43 | var instance = new Easing();
44 |
45 | module.exports = instance;
--------------------------------------------------------------------------------
/lib/Loop.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
4 |
5 | var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
6 |
7 | /*
8 | * Loop utility using requestAnimationFrame
9 | */
10 | var w = global.window || 0,
11 | raf = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.mozRequestAnimationFrame || w.msRequestAnimationFrame || w.oRequestAnimationFrame || function (c) {
12 | global.setTimeout(c, 1000 / 60);
13 | },
14 | caf = w.cancelAnimationFrame || w.webkitCancelAnimationFrame || w.mozCancelAnimationFrame || w.msCancelAnimationFrame || w.oCancelAnimationFrame || global.clearTimeout;
15 |
16 | var Loop = (function () {
17 | function Loop(callback) {
18 | _classCallCheck(this, Loop);
19 |
20 | this._callback = callback;
21 | }
22 |
23 | _createClass(Loop, {
24 | start: {
25 | value: function start() {
26 | // keep loop while the callback returns true
27 | this._startTime = Date.now();
28 | this._loop();
29 | }
30 | },
31 | _loop: {
32 | value: function _loop() {
33 | var _this = this;
34 |
35 | if (!this._callback) {
36 | return;
37 | }
38 | var keep = this._callback();
39 | if (keep) {
40 | var exec = function () {
41 | _this._timer = raf(_this._loop.bind(_this));
42 | };
43 | // handle promise
44 | if (keep.then) {
45 | keep.then(exec);
46 | } else {
47 | exec();
48 | }
49 | }
50 | }
51 | },
52 | end: {
53 | value: function end() {
54 | if (this._timer) {
55 | caf(this._timer);
56 | this._timer = null;
57 | }
58 | this._startTime = null;
59 | }
60 | },
61 | timeDiff: {
62 | value: function timeDiff() {
63 | return Date.now() - this._startTime;
64 | }
65 | }
66 | });
67 |
68 | return Loop;
69 | })();
70 |
71 | module.exports = Loop;
--------------------------------------------------------------------------------
/lib/ReactStateAnimation.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
4 |
5 | var Animate = _interopRequire(require("./Animate"));
6 |
7 | var Loop = _interopRequire(require("./Loop"));
8 |
9 | var ReactStateAnimation = Animate;
10 | ReactStateAnimation.Loop = Loop;
11 |
12 | module.exports = ReactStateAnimation;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-state-animation",
3 | "version": "0.1.1",
4 | "description": "Simple animations with React state",
5 | "main": "lib/ReactStateAnimation.js",
6 | "scripts": {
7 | "start": "./node_modules/.bin/gulp",
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "https://github.com/tejitak/react-state-animation.git"
13 | },
14 | "keywords": [
15 | "react",
16 | "react-canvas",
17 | "animation",
18 | "tween",
19 | "transition",
20 | "state",
21 | "easing"
22 | ],
23 | "author": "tejitak",
24 | "license": "MIT",
25 | "bugs": {
26 | "url": "https://github.com/tejitak/react-state-animation/issues"
27 | },
28 | "homepage": "https://github.com/tejitak/react-state-animation",
29 | "dependencies": {
30 | "d3-ease": "^0.1.3"
31 | },
32 | "peerDependencies": {
33 | "react": ">=0.13.x"
34 | },
35 | "devDependencies": {
36 | "babel": "^5.5.6",
37 | "babel-core": "^5.5.6",
38 | "babel-loader": "^5.1.4",
39 | "del": "^1.1.1",
40 | "envify": "^3.2.0",
41 | "gulp": "^3.8.10",
42 | "gulp-babel": "^4.0.0",
43 | "gulp-connect": "^2.2.0",
44 | "gulp-if": "^1.2.5",
45 | "gulp-uglify": "~1.0.2",
46 | "gulp-webpack": "^1.2.0",
47 | "react-canvas": "0.0.1",
48 | "webpack": "^1.7.3",
49 | "yargs": "^3.5.4"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Animate.js:
--------------------------------------------------------------------------------
1 | import Loop from './Loop'
2 | import {ease} from 'd3-ease'
3 |
4 | let eases = [
5 | 'linear-in',
6 | 'linear-out',
7 | 'linear-in-out',
8 | 'quad-in',
9 | 'quad-out',
10 | 'quad-in-out',
11 | 'cubic-in',
12 | 'cubic-out',
13 | 'cubic-in-out',
14 | 'poly-in',
15 | 'poly-out',
16 | 'poly-in-out',
17 | 'sin-in',
18 | 'sin-out',
19 | 'sin-in-out',
20 | 'exp-in',
21 | 'exp-out',
22 | 'exp-in-out',
23 | 'circle-in',
24 | 'circle-out',
25 | 'circle-in-out',
26 | 'bounce-in',
27 | 'bounce-out',
28 | 'bounce-in-out',
29 | 'back-in',
30 | 'back-out',
31 | 'back-in-out',
32 | 'elastic-in',
33 | 'elastic-out',
34 | 'elastic-in-out'
35 | ], Easing = {};
36 |
37 | /**
38 | * React state animation wrapper
39 | * - update state value by requestAnimationFrame loop
40 | */
41 | export default class Animate {
42 |
43 | constructor(component) {
44 | this._component = component;
45 |
46 | // generate an interface function for each ease.
47 | eases.forEach( (e) => {
48 | // convert to camelCase
49 | var easeName = e.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
50 |
51 | // add instance methods dynamically
52 | this[easeName] = function(prop, end, duration) {
53 | return this.animate(prop, end, duration, easeName)
54 | }
55 |
56 | Easing[easeName] = ease(e)
57 |
58 | });
59 | }
60 |
61 | /**
62 | * Get state value
63 | * if the prop is not in state regular property
64 | */
65 | _getStateValue(prop) {
66 | var c = this._component,
67 | v = c.state && c.state[prop]
68 | return v === undefined ? c[prop] : v
69 | }
70 |
71 | /**
72 | * Set value to state
73 | * if the prop is not in state, set value to regular property with force update
74 | */
75 | _updateStateValue(prop, v) {
76 | return new Promise((resolve, reject) => {
77 | var c = this._component
78 | if(c.state && c.state[prop] !== undefined){
79 | var state = {}
80 | state[prop] = v
81 | c.setState(state, resolve)
82 | }else{
83 | c[prop] = v
84 | c.forceUpdate()
85 | resolve()
86 | }
87 | })
88 | }
89 |
90 | /**
91 | * Updates multiple properties within
92 | * @param prop {Array} array of targeted states= {state: {string}, target: {number}}
93 | * @param values {Array} array of values to be set
94 | * @returns {Promise}
95 | */
96 | _updateStateMap(prop, values) {
97 |
98 | return new Promise((resolve, reject) => {
99 | var c = this._component,
100 | state = {};
101 | // build up changed state
102 | for(var i = 0; i < prop.length; i++) {
103 | state[prop[i].state] = values[i];
104 | }
105 | c.setState(state, resolve);
106 | });
107 | }
108 |
109 | _start(loopCallback) {
110 | this._loop = new Loop(loopCallback)
111 | this._loop.start()
112 | }
113 |
114 | animate(prop, end, duration, easing) {
115 | if(!Easing[easing]) {
116 | console.log("Specified easing does not exist: " + easing)
117 | return
118 | }
119 | return new Promise((resolve, reject) => {
120 | var begin = this._getStateValue(prop)
121 | this._start(() => {
122 | return this._anim(prop, begin, end, duration, easing, resolve)
123 | })
124 | })
125 | }
126 |
127 | manimate(prop, duration, easing) {
128 | if (!Easing[easing]) {
129 | console.log("Specified easing does not exist: " + easing);
130 | return;
131 | }
132 | return new Promise((resolve, reject) => {
133 | // gather array begin States
134 | var begins = [],
135 | ends = [];
136 | for(var i = 0; i < prop.length; i++) {
137 | var b = this._getStateValue(prop[i].state);
138 | var e = prop[i].target;
139 | begins.push(b);
140 | ends.push(e);
141 | }
142 | // start multi-anim
143 | this._start(() => {
144 | return this._multianim(prop, begins, ends, duration, easing, resolve);
145 | });
146 | });
147 | }
148 |
149 | // for override on each loop
150 | onProcess(prop, value, progress) {
151 | }
152 |
153 | /**
154 | * Start animation
155 | * - prop is a react state property
156 | * - end is a goal value of the state
157 | */
158 | _anim(prop, begin, end, duration, easing, resolve) {
159 | if(!this._loop){
160 | resolve()
161 | return false
162 | }
163 | var progress = Easing[easing](this._loop.timeDiff() / duration),
164 | distance = Math.abs(begin - end),
165 | diff = progress * distance,
166 | operator = begin > end ? -1 : 1,
167 | value = begin + diff * operator
168 | this.onProcess(prop, value, progress)
169 | if(progress < 1) {
170 | // return promise to keep loop
171 | return this._updateStateValue(prop, value)
172 | }else{
173 | this.stop()
174 | this._updateStateValue(prop, end).then(() => {
175 | resolve()
176 | })
177 | return false
178 | }
179 | }
180 |
181 | _multianim(prop, begins, ends, duration, easing, resolve) {
182 | if(!this._loop) {
183 | resolve();
184 | return false;
185 | }
186 | var progress = Easing[easing](this._loop.timeDiff() / duration),
187 | newValues = [];
188 |
189 | // step through all states
190 | for(var i = 0; i < prop.length; i++) {
191 | var begin = begins[i],
192 | end = ends[i],
193 | p = prop[i].state,
194 | distance = Math.abs(begin - end),
195 | diff = progress * distance,
196 | operator = begin > end ? -1 : 1,
197 | value = begin + diff * operator;
198 |
199 | this.onProcess(p, value, progress);
200 |
201 | newValues.push(value);
202 | }
203 |
204 | if(progress < 1) {
205 | return this._updateStateMap(prop, newValues);
206 | } else {
207 | this.stop();
208 | this._updateStateMap(prop, ends).then(function () {
209 | resolve();
210 | });
211 | return false;
212 | }
213 | }
214 |
215 | stop() {
216 | if(this._loop) {
217 | this._loop.end()
218 | this._loop = null
219 | }
220 | return this
221 | }
222 |
223 | }
224 |
--------------------------------------------------------------------------------
/src/Loop.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Loop utility using requestAnimationFrame
3 | */
4 | var w = (global.window || 0),
5 | raf = w['requestAnimationFrame'] || w['webkitRequestAnimationFrame'] || w['mozRequestAnimationFrame'] || w['msRequestAnimationFrame'] || w['oRequestAnimationFrame'] || function(c){ global.setTimeout(c, 1000 / 60) },
6 | caf = w['cancelAnimationFrame'] || w['webkitCancelAnimationFrame'] || w['mozCancelAnimationFrame'] || w['msCancelAnimationFrame'] || w['oCancelAnimationFrame'] || global.clearTimeout
7 |
8 | export default class Loop {
9 |
10 | constructor(callback) {
11 | this._callback = callback;
12 | }
13 |
14 | start() {
15 | // keep loop while the callback returns true
16 | this._startTime = Date.now()
17 | this._loop()
18 | }
19 |
20 | _loop() {
21 | if(!this._callback){ return }
22 | var keep = this._callback()
23 | if(keep) {
24 | var exec = ()=>{
25 | this._timer = raf(this._loop.bind(this));
26 | }
27 | // handle promise
28 | if(keep.then){
29 | keep.then(exec)
30 | }else{
31 | exec()
32 | }
33 | }
34 | }
35 |
36 | end() {
37 | if(this._timer) {
38 | caf(this._timer)
39 | this._timer = null
40 | }
41 | this._startTime = null
42 | }
43 |
44 | timeDiff() {
45 | return Date.now() - this._startTime
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/ReactStateAnimation.js:
--------------------------------------------------------------------------------
1 | import Animate from './Animate'
2 | import Loop from './Loop'
3 |
4 | var ReactStateAnimation = Animate
5 | ReactStateAnimation.Loop = Loop
6 |
7 | export default ReactStateAnimation
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | cache: true,
3 |
4 | watch: true,
5 |
6 | entry: {
7 | 'demo': ['./examples/demo/app.js'],
8 | 'canvas': ['./examples/demo/canvas.js'],
9 | 'fps': ['./examples/fps/app.js']
10 | },
11 |
12 | output: {
13 | filename: '[name].js'
14 | },
15 |
16 | devtool: 'inline-source-map',
17 |
18 | module: {
19 | loaders: [
20 | { test: /\.js$|\.jsx$/, exclude: /node_modules|build/, loader: 'babel-loader'}
21 | ]
22 | },
23 |
24 | resolve: {
25 | root: __dirname,
26 | alias: {
27 | 'react-state-animation': 'src/ReactStateAnimation.js'
28 | },
29 | extensions: ['', '.js', '.jsx']
30 | }
31 | };
32 |
--------------------------------------------------------------------------------