-
Notifications
You must be signed in to change notification settings - Fork 0
/
StateAnimated.js
93 lines (82 loc) · 2.63 KB
/
StateAnimated.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import React from 'react';
import PropTypes from 'prop-types';
import { View, Text, Image, Easing } from 'react-native';
import * as Animatable from 'react-native-animatable';
function createStateAnimatedComponent(rawComponent) {
const AnimatableComponent = Animatable.createAnimatableComponent(rawComponent);
return React.createClass({
displayName: `StateAnimated.${rawComponent.displayName}`,
propTypes: {
currentState: PropTypes.string,
states: PropTypes.objectOf(PropTypes.shape({
style: PropTypes.any,
duration: PropTypes.number,
easing: PropTypes.instanceOf(Easing),
})).isRequired,
style: PropTypes.any,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
]),
},
componentDidUpdate(prevProps, prevState) {
const oldStateName = prevProps.currentState;
const newStateName = this.props.currentState;
if (newStateName != null && newStateName !== oldStateName) {
this.applyPattern(newStateName);
}
},
_refAnimView: null,
_defaultState: null,
applyPattern(pattern) {
const tokens = pattern.split(',').map(t => t.trim());
if (tokens.length === 0) {
return;
}
let token = tokens.shift();
let timeOut = 400;
if (isNaN(token)) {
const stateKeys = Object.keys(this.props.states);
if (!stateKeys.includes(token)) {
if (stateKeys.includes('*')) {
token = '*';
} else {
throw new Error(`Undefined state: ${token}`);
}
} else {
const newState = this.props.states[token];
this._refAnimView.stopAnimation();
if (newState.duration) {
timeOut = newState.duration;
}
this._refAnimView.transitionTo(newState.style, timeOut, newState.easing);
}
} else {
timeOut = parseFloat(token);
}
setTimeout(() => {
this.applyPattern(tokens.join(','));
}, timeOut);
},
render() {
const { currentState, states, style, children, ...otherProps } = this.props;
if (this._defaultState === null) {
this._defaultState = currentState;
}
return (
<AnimatableComponent
ref={c => { this._refAnimView = c; }}
style={[style, states[this._defaultState].style]}
{...otherProps}>
{children}
</AnimatableComponent>
);
},
});
}
export default {
createStateAnimatedComponent,
View: createStateAnimatedComponent(View),
Text: createStateAnimatedComponent(Text),
Image: createStateAnimatedComponent(Image),
};