forked from oblador/react-native-animatable
-
Notifications
You must be signed in to change notification settings - Fork 0
/
createAnimation.js
80 lines (68 loc) · 1.72 KB
/
createAnimation.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
import flattenStyle from './flattenStyle';
function compareNumbers(a, b) {
return a - b;
}
function notNull(value) {
return value !== null;
}
function parsePosition(value) {
if (value === 'from') {
return 0;
}
if (value === 'to') {
return 1;
}
const parsed = parseFloat(value, 10);
if (Number.isNaN(parsed) || parsed < 0 || parsed > 1) {
return null;
}
return parsed;
}
const cache = {};
export default function createAnimation(definition) {
const cacheKey = JSON.stringify(definition);
if (cache[cacheKey]) {
return cache[cacheKey];
}
const positions = Object.keys(definition)
.map(parsePosition)
.filter(notNull);
positions.sort(compareNumbers);
if (positions.length < 2) {
throw new Error('Animation definitions must have at least two values.');
}
const compiled = {};
if (definition.easing) {
compiled.easing = definition.easing;
}
if (definition.style) {
compiled.style = definition.style;
}
for (let i = 0; i < positions.length; i += 1) {
const position = positions[i];
let keyframe = definition[position];
if (!keyframe) {
if (position === 0) {
keyframe = definition.from;
} else if (position === 1) {
keyframe = definition.to;
}
}
if (!keyframe) {
throw new Error('Missing animation keyframe, this should not happen');
}
keyframe = flattenStyle(keyframe);
Object.keys(keyframe).forEach(key => {
if (!(key in compiled)) {
compiled[key] = {
inputRange: [],
outputRange: [],
};
}
compiled[key].inputRange.push(position);
compiled[key].outputRange.push(keyframe[key]);
});
}
cache[cacheKey] = compiled;
return compiled;
}