-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathconfetti.js
More file actions
133 lines (125 loc) · 3.59 KB
/
confetti.js
File metadata and controls
133 lines (125 loc) · 3.59 KB
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import React from 'react';
import {Animated } from 'react-native';
export function ConfettiItem({ color, translateX, translateY, opacity, rotateX, rotateZ }) {
const spinX = rotateX.interpolate({
inputRange: [0, 10],
outputRange: ['0deg', '360deg'],
});
const spinZ = rotateZ.interpolate({
inputRange: [0, 10],
outputRange: ['0deg', '360deg'],
});
const itemStyle = {
backgroundColor: color,
height: 8,
width: 8,
opacity,
transform: [
{ translateX },
{ translateY },
{ rotateX: spinX },
{ rotateZ: spinZ },
],
position: 'absolute',
};
return (
<Animated.View style={itemStyle}/>
);
}
export function generateConfettiItems(translations, count, colors) {
const items = [];
for (let i = 0; i < count; i++) {
const { transform, opacity, rotateX, rotateZ } = translations[i];
const item = (
<ConfettiItem
key={i}
color={colors[i % colors.length]}
translateX={transform.x}
translateY={transform.y}
rotateX={rotateX}
rotateZ={rotateZ}
opacity={opacity}
/>
);
items.push(item);
}
return items;
}
export function generateConfettiInitialTranslations(count = 20, initialOpacity = 1) {
const translations = [];
for (let i = 0; i < count; i++) {
const translation = {
transform: new Animated.ValueXY(0, 0),
opacity: new Animated.Value(initialOpacity),
rotateX: new Animated.Value(0),
rotateZ: new Animated.Value(0),
};
translations.push(translation);
}
return translations;
}
export function generateConfettiAnimations(translations, params) {
return translations.map((item, index) => generateConfettiAnimation(item, index, translations.length, params));
}
function generateConfettiAnimation({ transform, opacity, rotateX, rotateZ }, index, count, params) {
const { initialSpeed, spread, deacceleration, rotationXSpeed, rotationZSpeed, useNativeDriver } = params;
const degrees = 0;
const angle = degrees * Math.PI / 180;
const vx = Math.cos(angle);
const vy = Math.sin(angle);
const spreadSpeed = (Math.random() - 0.5) * 3 * initialSpeed * spread;
const flySpeed = (-1.0 - Math.random() * 2) * initialSpeed;
const xSpeed = spreadSpeed * vx + flySpeed * vy;
const ySpeed = flySpeed * vx + flySpeed * vy;
const upAnimation =
Animated.decay(transform, {
// coast to a stop
velocity: { x: xSpeed, y: ySpeed }, // velocity from gesture release
deceleration: 0.989 + (1 - deacceleration) / 100,
useNativeDriver,
});
const duration = 2000 + Math.random() * 100;
const downAnimation = Animated.timing( // Animate over time
transform.y, // The animated value to drive
{
toValue: 100 + Math.random() * 100, // Animate to opacity: 1 (opaque)
duration, // Make it take a while
useNativeDriver,
},
);
const disapearAnimation = Animated.timing( // Animate over time
opacity, // The animated value to drive
{
toValue: 0, // Animate to opacity: 1 (opaque)
duration, // Make it take a while
useNativeDriver,
},
);
const rotateXAnimation = Animated.timing(
rotateX,
{
toValue: (Math.random() * 3) * rotationXSpeed,
duration,
useNativeDriver,
},
);
const rotateZAnimation = Animated.timing(
rotateZ,
{
toValue: (Math.random() * 5) * rotationZSpeed,
duration,
useNativeDriver,
},
);
Animated.parallel([
Animated.sequence([
upAnimation,
Animated.parallel([
disapearAnimation,
downAnimation,
]),
]),
rotateXAnimation,
rotateZAnimation,
]).start();
}