react-native-confetti-reanimated 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/ConfettiParticle.js +42 -18
- package/lib/commonjs/ConfettiParticle.js.map +1 -1
- package/lib/module/ConfettiParticle.js +42 -18
- package/lib/module/ConfettiParticle.js.map +1 -1
- package/lib/typescript/ConfettiParticle.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ConfettiParticle.tsx +43 -17
|
@@ -24,6 +24,7 @@ const ConfettiParticle = ({
|
|
|
24
24
|
const velX = (0, _reactNativeReanimated.useSharedValue)(particle.velocity.x);
|
|
25
25
|
const velY = (0, _reactNativeReanimated.useSharedValue)(particle.velocity.y);
|
|
26
26
|
const startTime = (0, _reactNativeReanimated.useSharedValue)(Date.now());
|
|
27
|
+
const lastFrameTime = (0, _reactNativeReanimated.useSharedValue)(Date.now());
|
|
27
28
|
const isComplete = (0, _reactNativeReanimated.useSharedValue)(false);
|
|
28
29
|
|
|
29
30
|
// Canvas-confetti realistic wobble and tilt variables
|
|
@@ -36,7 +37,9 @@ const ConfettiParticle = ({
|
|
|
36
37
|
const tick = (0, _reactNativeReanimated.useSharedValue)(0);
|
|
37
38
|
const totalTicks = (0, _reactNativeReanimated.useSharedValue)(Math.max(1, Math.round(config.ticks ?? config.tickDuration ?? duration / 1000 * 60)));
|
|
38
39
|
(0, _react.useEffect)(() => {
|
|
39
|
-
|
|
40
|
+
const now = Date.now();
|
|
41
|
+
startTime.value = now;
|
|
42
|
+
lastFrameTime.value = now;
|
|
40
43
|
tick.value = 0;
|
|
41
44
|
totalTicks.value = Math.max(1, Math.round(config.ticks ?? config.tickDuration ?? duration / 1000 * 60));
|
|
42
45
|
|
|
@@ -54,54 +57,75 @@ const ConfettiParticle = ({
|
|
|
54
57
|
(0, _reactNativeReanimated.cancelAnimation)(rotation);
|
|
55
58
|
(0, _reactNativeReanimated.cancelAnimation)(opacity);
|
|
56
59
|
};
|
|
57
|
-
}, [config.tickDuration, config.ticks, duration, onComplete, opacity, isComplete, startTime, totalTicks, translateX, translateY, rotation, tick]);
|
|
60
|
+
}, [config.tickDuration, config.ticks, duration, onComplete, opacity, isComplete, startTime, lastFrameTime, totalTicks, translateX, translateY, rotation, tick]);
|
|
58
61
|
|
|
59
62
|
// Real-time physics simulation using frame callback
|
|
60
|
-
|
|
63
|
+
// Frame-rate independent: uses deltaTime to ensure consistent speed across devices
|
|
64
|
+
(0, _reactNativeReanimated.useFrameCallback)(frameInfo => {
|
|
61
65
|
'worklet';
|
|
62
66
|
|
|
63
67
|
if (isComplete.value) {
|
|
64
68
|
return;
|
|
65
69
|
}
|
|
66
|
-
const
|
|
70
|
+
const currentTime = Date.now();
|
|
71
|
+
const elapsed = currentTime - startTime.value;
|
|
67
72
|
if (elapsed >= duration) {
|
|
68
73
|
isComplete.value = true;
|
|
69
74
|
return;
|
|
70
75
|
}
|
|
71
76
|
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
// Calculate deltaTime normalized to 60fps (16.67ms per frame)
|
|
78
|
+
// This ensures consistent animation speed regardless of device frame rate
|
|
79
|
+
const frameDelta = currentTime - lastFrameTime.value;
|
|
80
|
+
|
|
81
|
+
// Handle first frame or invalid deltas
|
|
82
|
+
if (frameDelta <= 0 || frameDelta > 1000) {
|
|
83
|
+
lastFrameTime.value = currentTime;
|
|
84
|
+
return; // Skip this frame
|
|
85
|
+
}
|
|
86
|
+
const deltaTime = frameDelta / 16.67;
|
|
87
|
+
lastFrameTime.value = currentTime;
|
|
88
|
+
|
|
89
|
+
// Clamp deltaTime to prevent large jumps (e.g., when app resumes from background)
|
|
90
|
+
// Max 2.0 means we allow up to 2x normal frame time (30fps equivalent)
|
|
91
|
+
const clampedDelta = Math.min(deltaTime, 2.0);
|
|
92
|
+
|
|
93
|
+
// Update position based on current velocity (scaled by deltaTime for frame-rate independence)
|
|
94
|
+
// Velocity is in pixels per frame at 60fps, so we scale by deltaTime
|
|
95
|
+
translateX.value += velX.value * clampedDelta;
|
|
96
|
+
translateY.value += velY.value * clampedDelta;
|
|
75
97
|
|
|
76
98
|
// Apply gravity (increases downward velocity) - realistic physics!
|
|
77
|
-
|
|
99
|
+
// Gravity is per frame at 60fps, so scale by deltaTime
|
|
100
|
+
velY.value += config.gravity * clampedDelta;
|
|
78
101
|
|
|
79
102
|
// Apply drift (horizontal wind)
|
|
80
|
-
velX.value += config.drift;
|
|
103
|
+
velX.value += config.drift * clampedDelta;
|
|
81
104
|
|
|
82
|
-
// Apply decay (air resistance)
|
|
83
|
-
velX.value *= config.decay;
|
|
84
|
-
velY.value *= config.decay;
|
|
105
|
+
// Apply decay (air resistance) - decay per frame, so raise to power of deltaTime
|
|
106
|
+
velX.value *= Math.pow(config.decay, clampedDelta);
|
|
107
|
+
velY.value *= Math.pow(config.decay, clampedDelta);
|
|
85
108
|
|
|
86
109
|
// Update rotation - ALL particles spin faster when moving fast, slower when slowing down
|
|
87
110
|
const speed = Math.sqrt(velX.value * velX.value + velY.value * velY.value);
|
|
88
111
|
const speedBoost = 1 + speed / 20;
|
|
89
|
-
rotation.value += particle.rotationVelocity * speedBoost;
|
|
112
|
+
rotation.value += particle.rotationVelocity * speedBoost * clampedDelta;
|
|
90
113
|
|
|
91
114
|
// Canvas-confetti wobble effect (creates side-to-side flutter)
|
|
92
|
-
wobble.value += wobbleSpeed.value;
|
|
115
|
+
wobble.value += wobbleSpeed.value * clampedDelta;
|
|
93
116
|
|
|
94
117
|
// Canvas-confetti tilt animation (creates 3D tumbling effect)
|
|
95
|
-
tiltAngle.value += 0.1;
|
|
118
|
+
tiltAngle.value += 0.1 * clampedDelta;
|
|
96
119
|
tiltSin.value = Math.sin(tiltAngle.value);
|
|
97
120
|
tiltCos.value = Math.cos(tiltAngle.value);
|
|
98
121
|
random.value = Math.random() + 2;
|
|
99
122
|
|
|
100
|
-
// Update tick for progressive opacity fade
|
|
101
|
-
|
|
123
|
+
// Update tick for progressive opacity fade (time-based, not frame-based)
|
|
124
|
+
// Use elapsed time instead of frame count for frame-rate independence
|
|
125
|
+
const progress = Math.min(1, elapsed / duration);
|
|
126
|
+
tick.value = progress * totalTicks.value;
|
|
102
127
|
|
|
103
128
|
// Canvas-confetti progressive fade: opacity decreases linearly over lifetime
|
|
104
|
-
const progress = Math.min(1, tick.value / totalTicks.value);
|
|
105
129
|
opacity.value = 1 - progress;
|
|
106
130
|
});
|
|
107
131
|
const animatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ConfettiParticle","particle","config","duration","onComplete","translateX","useSharedValue","translateY","rotation","opacity","velX","velocity","x","velY","y","startTime","Date","now","isComplete","wobble","Math","random","wobbleSpeed","min","tiltAngle","tiltSin","tiltCos","tick","totalTicks","max","round","ticks","tickDuration","useEffect","value","timer","setTimeout","clearTimeout","cancelAnimation","useFrameCallback","elapsed","gravity","drift","decay","speed","sqrt","speedBoost","rotationVelocity","sin","cos","progress","animatedStyle","useAnimatedStyle","wobbleX","scalar","wobbleY","x1","y1","x2","y2","scaleX","abs","scaleY","transform","rotate","renderShape","shape","size","width","jsx","View","style","styles","circle","height","backgroundColor","color","fontSize","Text","star","textShadowColor","children","container","left","top","exports","StyleSheet","create","position","borderRadius","textShadowOffset","textShadowRadius"],"sourceRoot":"../../src","sources":["ConfettiParticle.tsx"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AACA,IAAAE,sBAAA,GAAAH,uBAAA,CAAAC,OAAA;AAKiC,IAAAG,WAAA,GAAAH,OAAA;AAAA,SAAAD,wBAAAK,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAP,uBAAA,YAAAA,CAAAK,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAU1B,MAAMkB,gBAAiC,GAAGA,CAAC;EAAEC,QAAQ;EAAEC,MAAM;EAAEC,QAAQ;EAAEC;AAAW,CAAC,KAAK;EAC/F,MAAMC,UAAU,GAAG,IAAAC,qCAAc,EAAC,CAAC,CAAC;EACpC,MAAMC,UAAU,GAAG,IAAAD,qCAAc,EAAC,CAAC,CAAC;EACpC,MAAME,QAAQ,GAAG,IAAAF,qCAAc,EAACL,QAAQ,CAACO,QAAQ,CAAC;EAClD,MAAMC,OAAO,GAAG,IAAAH,qCAAc,EAAC,CAAC,CAAC;;EAEjC;EACA,MAAMI,IAAI,GAAG,IAAAJ,qCAAc,EAACL,QAAQ,CAACU,QAAQ,CAACC,CAAC,CAAC;EAChD,MAAMC,IAAI,GAAG,IAAAP,qCAAc,EAACL,QAAQ,CAACU,QAAQ,CAACG,CAAC,CAAC;EAChD,MAAMC,SAAS,GAAG,IAAAT,qCAAc,EAACU,IAAI,CAACC,GAAG,CAAC,CAAC,CAAC;EAC5C,MAAMC,
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ConfettiParticle","particle","config","duration","onComplete","translateX","useSharedValue","translateY","rotation","opacity","velX","velocity","x","velY","y","startTime","Date","now","lastFrameTime","isComplete","wobble","Math","random","wobbleSpeed","min","tiltAngle","tiltSin","tiltCos","tick","totalTicks","max","round","ticks","tickDuration","useEffect","value","timer","setTimeout","clearTimeout","cancelAnimation","useFrameCallback","frameInfo","currentTime","elapsed","frameDelta","deltaTime","clampedDelta","gravity","drift","pow","decay","speed","sqrt","speedBoost","rotationVelocity","sin","cos","progress","animatedStyle","useAnimatedStyle","wobbleX","scalar","wobbleY","x1","y1","x2","y2","scaleX","abs","scaleY","transform","rotate","renderShape","shape","size","width","jsx","View","style","styles","circle","height","backgroundColor","color","fontSize","Text","star","textShadowColor","children","container","left","top","exports","StyleSheet","create","position","borderRadius","textShadowOffset","textShadowRadius"],"sourceRoot":"../../src","sources":["ConfettiParticle.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -19,6 +19,7 @@ export const ConfettiParticle = ({
|
|
|
19
19
|
const velX = useSharedValue(particle.velocity.x);
|
|
20
20
|
const velY = useSharedValue(particle.velocity.y);
|
|
21
21
|
const startTime = useSharedValue(Date.now());
|
|
22
|
+
const lastFrameTime = useSharedValue(Date.now());
|
|
22
23
|
const isComplete = useSharedValue(false);
|
|
23
24
|
|
|
24
25
|
// Canvas-confetti realistic wobble and tilt variables
|
|
@@ -31,7 +32,9 @@ export const ConfettiParticle = ({
|
|
|
31
32
|
const tick = useSharedValue(0);
|
|
32
33
|
const totalTicks = useSharedValue(Math.max(1, Math.round(config.ticks ?? config.tickDuration ?? duration / 1000 * 60)));
|
|
33
34
|
useEffect(() => {
|
|
34
|
-
|
|
35
|
+
const now = Date.now();
|
|
36
|
+
startTime.value = now;
|
|
37
|
+
lastFrameTime.value = now;
|
|
35
38
|
tick.value = 0;
|
|
36
39
|
totalTicks.value = Math.max(1, Math.round(config.ticks ?? config.tickDuration ?? duration / 1000 * 60));
|
|
37
40
|
|
|
@@ -49,54 +52,75 @@ export const ConfettiParticle = ({
|
|
|
49
52
|
cancelAnimation(rotation);
|
|
50
53
|
cancelAnimation(opacity);
|
|
51
54
|
};
|
|
52
|
-
}, [config.tickDuration, config.ticks, duration, onComplete, opacity, isComplete, startTime, totalTicks, translateX, translateY, rotation, tick]);
|
|
55
|
+
}, [config.tickDuration, config.ticks, duration, onComplete, opacity, isComplete, startTime, lastFrameTime, totalTicks, translateX, translateY, rotation, tick]);
|
|
53
56
|
|
|
54
57
|
// Real-time physics simulation using frame callback
|
|
55
|
-
|
|
58
|
+
// Frame-rate independent: uses deltaTime to ensure consistent speed across devices
|
|
59
|
+
useFrameCallback(frameInfo => {
|
|
56
60
|
'worklet';
|
|
57
61
|
|
|
58
62
|
if (isComplete.value) {
|
|
59
63
|
return;
|
|
60
64
|
}
|
|
61
|
-
const
|
|
65
|
+
const currentTime = Date.now();
|
|
66
|
+
const elapsed = currentTime - startTime.value;
|
|
62
67
|
if (elapsed >= duration) {
|
|
63
68
|
isComplete.value = true;
|
|
64
69
|
return;
|
|
65
70
|
}
|
|
66
71
|
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
// Calculate deltaTime normalized to 60fps (16.67ms per frame)
|
|
73
|
+
// This ensures consistent animation speed regardless of device frame rate
|
|
74
|
+
const frameDelta = currentTime - lastFrameTime.value;
|
|
75
|
+
|
|
76
|
+
// Handle first frame or invalid deltas
|
|
77
|
+
if (frameDelta <= 0 || frameDelta > 1000) {
|
|
78
|
+
lastFrameTime.value = currentTime;
|
|
79
|
+
return; // Skip this frame
|
|
80
|
+
}
|
|
81
|
+
const deltaTime = frameDelta / 16.67;
|
|
82
|
+
lastFrameTime.value = currentTime;
|
|
83
|
+
|
|
84
|
+
// Clamp deltaTime to prevent large jumps (e.g., when app resumes from background)
|
|
85
|
+
// Max 2.0 means we allow up to 2x normal frame time (30fps equivalent)
|
|
86
|
+
const clampedDelta = Math.min(deltaTime, 2.0);
|
|
87
|
+
|
|
88
|
+
// Update position based on current velocity (scaled by deltaTime for frame-rate independence)
|
|
89
|
+
// Velocity is in pixels per frame at 60fps, so we scale by deltaTime
|
|
90
|
+
translateX.value += velX.value * clampedDelta;
|
|
91
|
+
translateY.value += velY.value * clampedDelta;
|
|
70
92
|
|
|
71
93
|
// Apply gravity (increases downward velocity) - realistic physics!
|
|
72
|
-
|
|
94
|
+
// Gravity is per frame at 60fps, so scale by deltaTime
|
|
95
|
+
velY.value += config.gravity * clampedDelta;
|
|
73
96
|
|
|
74
97
|
// Apply drift (horizontal wind)
|
|
75
|
-
velX.value += config.drift;
|
|
98
|
+
velX.value += config.drift * clampedDelta;
|
|
76
99
|
|
|
77
|
-
// Apply decay (air resistance)
|
|
78
|
-
velX.value *= config.decay;
|
|
79
|
-
velY.value *= config.decay;
|
|
100
|
+
// Apply decay (air resistance) - decay per frame, so raise to power of deltaTime
|
|
101
|
+
velX.value *= Math.pow(config.decay, clampedDelta);
|
|
102
|
+
velY.value *= Math.pow(config.decay, clampedDelta);
|
|
80
103
|
|
|
81
104
|
// Update rotation - ALL particles spin faster when moving fast, slower when slowing down
|
|
82
105
|
const speed = Math.sqrt(velX.value * velX.value + velY.value * velY.value);
|
|
83
106
|
const speedBoost = 1 + speed / 20;
|
|
84
|
-
rotation.value += particle.rotationVelocity * speedBoost;
|
|
107
|
+
rotation.value += particle.rotationVelocity * speedBoost * clampedDelta;
|
|
85
108
|
|
|
86
109
|
// Canvas-confetti wobble effect (creates side-to-side flutter)
|
|
87
|
-
wobble.value += wobbleSpeed.value;
|
|
110
|
+
wobble.value += wobbleSpeed.value * clampedDelta;
|
|
88
111
|
|
|
89
112
|
// Canvas-confetti tilt animation (creates 3D tumbling effect)
|
|
90
|
-
tiltAngle.value += 0.1;
|
|
113
|
+
tiltAngle.value += 0.1 * clampedDelta;
|
|
91
114
|
tiltSin.value = Math.sin(tiltAngle.value);
|
|
92
115
|
tiltCos.value = Math.cos(tiltAngle.value);
|
|
93
116
|
random.value = Math.random() + 2;
|
|
94
117
|
|
|
95
|
-
// Update tick for progressive opacity fade
|
|
96
|
-
|
|
118
|
+
// Update tick for progressive opacity fade (time-based, not frame-based)
|
|
119
|
+
// Use elapsed time instead of frame count for frame-rate independence
|
|
120
|
+
const progress = Math.min(1, elapsed / duration);
|
|
121
|
+
tick.value = progress * totalTicks.value;
|
|
97
122
|
|
|
98
123
|
// Canvas-confetti progressive fade: opacity decreases linearly over lifetime
|
|
99
|
-
const progress = Math.min(1, tick.value / totalTicks.value);
|
|
100
124
|
opacity.value = 1 - progress;
|
|
101
125
|
});
|
|
102
126
|
const animatedStyle = useAnimatedStyle(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useEffect","StyleSheet","Animated","useAnimatedStyle","useSharedValue","useFrameCallback","cancelAnimation","jsx","_jsx","ConfettiParticle","particle","config","duration","onComplete","translateX","translateY","rotation","opacity","velX","velocity","x","velY","y","startTime","Date","now","isComplete","wobble","Math","random","wobbleSpeed","min","tiltAngle","tiltSin","tiltCos","tick","totalTicks","max","round","ticks","tickDuration","value","timer","setTimeout","clearTimeout","elapsed","gravity","drift","decay","speed","sqrt","speedBoost","rotationVelocity","sin","cos","progress","animatedStyle","wobbleX","scalar","wobbleY","x1","y1","x2","y2","scaleX","abs","scaleY","transform","rotate","renderShape","shape","size","width","View","style","styles","circle","height","backgroundColor","color","fontSize","Text","star","textShadowColor","children","container","left","top","create","position","borderRadius","textShadowOffset","textShadowRadius"],"sourceRoot":"../../src","sources":["ConfettiParticle.tsx"],"mappings":";;AAAA,OAAOA,KAAK,IAAIC,SAAS,QAAQ,OAAO;AACxC,SAASC,UAAU,QAAQ,cAAc;AACzC,OAAOC,QAAQ,IACbC,gBAAgB,EAChBC,cAAc,EACdC,gBAAgB,EAChBC,eAAe,QACV,yBAAyB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAUjC,OAAO,MAAMC,gBAAiC,GAAGA,CAAC;EAAEC,QAAQ;EAAEC,MAAM;EAAEC,QAAQ;EAAEC;AAAW,CAAC,KAAK;EAC/F,MAAMC,UAAU,GAAGV,cAAc,CAAC,CAAC,CAAC;EACpC,MAAMW,UAAU,GAAGX,cAAc,CAAC,CAAC,CAAC;EACpC,MAAMY,QAAQ,GAAGZ,cAAc,CAACM,QAAQ,CAACM,QAAQ,CAAC;EAClD,MAAMC,OAAO,GAAGb,cAAc,CAAC,CAAC,CAAC;;EAEjC;EACA,MAAMc,IAAI,GAAGd,cAAc,CAACM,QAAQ,CAACS,QAAQ,CAACC,CAAC,CAAC;EAChD,MAAMC,IAAI,GAAGjB,cAAc,CAACM,QAAQ,CAACS,QAAQ,CAACG,CAAC,CAAC;EAChD,MAAMC,SAAS,GAAGnB,cAAc,CAACoB,IAAI,CAACC,GAAG,CAAC,CAAC,CAAC;EAC5C,MAAMC,
|
|
1
|
+
{"version":3,"names":["React","useEffect","StyleSheet","Animated","useAnimatedStyle","useSharedValue","useFrameCallback","cancelAnimation","jsx","_jsx","ConfettiParticle","particle","config","duration","onComplete","translateX","translateY","rotation","opacity","velX","velocity","x","velY","y","startTime","Date","now","lastFrameTime","isComplete","wobble","Math","random","wobbleSpeed","min","tiltAngle","tiltSin","tiltCos","tick","totalTicks","max","round","ticks","tickDuration","value","timer","setTimeout","clearTimeout","frameInfo","currentTime","elapsed","frameDelta","deltaTime","clampedDelta","gravity","drift","pow","decay","speed","sqrt","speedBoost","rotationVelocity","sin","cos","progress","animatedStyle","wobbleX","scalar","wobbleY","x1","y1","x2","y2","scaleX","abs","scaleY","transform","rotate","renderShape","shape","size","width","View","style","styles","circle","height","backgroundColor","color","fontSize","Text","star","textShadowColor","children","container","left","top","create","position","borderRadius","textShadowOffset","textShadowRadius"],"sourceRoot":"../../src","sources":["ConfettiParticle.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfettiParticle.d.ts","sourceRoot":"","sources":["../../src/ConfettiParticle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAQzC,OAAO,KAAK,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAExF,UAAU,KAAK;IACb,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"ConfettiParticle.d.ts","sourceRoot":"","sources":["../../src/ConfettiParticle.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAQzC,OAAO,KAAK,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAExF,UAAU,KAAK;IACb,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAyO5C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-confetti-reanimated",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "A high-performance confetti component for React Native using Reanimated 4, compatible with Expo",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
package/src/ConfettiParticle.tsx
CHANGED
|
@@ -25,6 +25,7 @@ export const ConfettiParticle: React.FC<Props> = ({ particle, config, duration,
|
|
|
25
25
|
const velX = useSharedValue(particle.velocity.x);
|
|
26
26
|
const velY = useSharedValue(particle.velocity.y);
|
|
27
27
|
const startTime = useSharedValue(Date.now());
|
|
28
|
+
const lastFrameTime = useSharedValue(Date.now());
|
|
28
29
|
const isComplete = useSharedValue(false);
|
|
29
30
|
|
|
30
31
|
// Canvas-confetti realistic wobble and tilt variables
|
|
@@ -40,7 +41,9 @@ export const ConfettiParticle: React.FC<Props> = ({ particle, config, duration,
|
|
|
40
41
|
);
|
|
41
42
|
|
|
42
43
|
useEffect(() => {
|
|
43
|
-
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
startTime.value = now;
|
|
46
|
+
lastFrameTime.value = now;
|
|
44
47
|
tick.value = 0;
|
|
45
48
|
totalTicks.value = Math.max(
|
|
46
49
|
1,
|
|
@@ -70,6 +73,7 @@ export const ConfettiParticle: React.FC<Props> = ({ particle, config, duration,
|
|
|
70
73
|
opacity,
|
|
71
74
|
isComplete,
|
|
72
75
|
startTime,
|
|
76
|
+
lastFrameTime,
|
|
73
77
|
totalTicks,
|
|
74
78
|
translateX,
|
|
75
79
|
translateY,
|
|
@@ -78,52 +82,74 @@ export const ConfettiParticle: React.FC<Props> = ({ particle, config, duration,
|
|
|
78
82
|
]);
|
|
79
83
|
|
|
80
84
|
// Real-time physics simulation using frame callback
|
|
81
|
-
|
|
85
|
+
// Frame-rate independent: uses deltaTime to ensure consistent speed across devices
|
|
86
|
+
useFrameCallback((frameInfo) => {
|
|
82
87
|
'worklet';
|
|
83
88
|
|
|
84
89
|
if (isComplete.value) {
|
|
85
90
|
return;
|
|
86
91
|
}
|
|
87
92
|
|
|
88
|
-
const
|
|
93
|
+
const currentTime = Date.now();
|
|
94
|
+
const elapsed = currentTime - startTime.value;
|
|
89
95
|
if (elapsed >= duration) {
|
|
90
96
|
isComplete.value = true;
|
|
91
97
|
return;
|
|
92
98
|
}
|
|
93
99
|
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
// Calculate deltaTime normalized to 60fps (16.67ms per frame)
|
|
101
|
+
// This ensures consistent animation speed regardless of device frame rate
|
|
102
|
+
const frameDelta = currentTime - lastFrameTime.value;
|
|
103
|
+
|
|
104
|
+
// Handle first frame or invalid deltas
|
|
105
|
+
if (frameDelta <= 0 || frameDelta > 1000) {
|
|
106
|
+
lastFrameTime.value = currentTime;
|
|
107
|
+
return; // Skip this frame
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const deltaTime = frameDelta / 16.67;
|
|
111
|
+
lastFrameTime.value = currentTime;
|
|
112
|
+
|
|
113
|
+
// Clamp deltaTime to prevent large jumps (e.g., when app resumes from background)
|
|
114
|
+
// Max 2.0 means we allow up to 2x normal frame time (30fps equivalent)
|
|
115
|
+
const clampedDelta = Math.min(deltaTime, 2.0);
|
|
116
|
+
|
|
117
|
+
// Update position based on current velocity (scaled by deltaTime for frame-rate independence)
|
|
118
|
+
// Velocity is in pixels per frame at 60fps, so we scale by deltaTime
|
|
119
|
+
translateX.value += velX.value * clampedDelta;
|
|
120
|
+
translateY.value += velY.value * clampedDelta;
|
|
97
121
|
|
|
98
122
|
// Apply gravity (increases downward velocity) - realistic physics!
|
|
99
|
-
|
|
123
|
+
// Gravity is per frame at 60fps, so scale by deltaTime
|
|
124
|
+
velY.value += config.gravity * clampedDelta;
|
|
100
125
|
|
|
101
126
|
// Apply drift (horizontal wind)
|
|
102
|
-
velX.value += config.drift;
|
|
127
|
+
velX.value += config.drift * clampedDelta;
|
|
103
128
|
|
|
104
|
-
// Apply decay (air resistance)
|
|
105
|
-
velX.value *= config.decay;
|
|
106
|
-
velY.value *= config.decay;
|
|
129
|
+
// Apply decay (air resistance) - decay per frame, so raise to power of deltaTime
|
|
130
|
+
velX.value *= Math.pow(config.decay, clampedDelta);
|
|
131
|
+
velY.value *= Math.pow(config.decay, clampedDelta);
|
|
107
132
|
|
|
108
133
|
// Update rotation - ALL particles spin faster when moving fast, slower when slowing down
|
|
109
134
|
const speed = Math.sqrt(velX.value * velX.value + velY.value * velY.value);
|
|
110
135
|
const speedBoost = 1 + speed / 20;
|
|
111
|
-
rotation.value += particle.rotationVelocity * speedBoost;
|
|
136
|
+
rotation.value += particle.rotationVelocity * speedBoost * clampedDelta;
|
|
112
137
|
|
|
113
138
|
// Canvas-confetti wobble effect (creates side-to-side flutter)
|
|
114
|
-
wobble.value += wobbleSpeed.value;
|
|
139
|
+
wobble.value += wobbleSpeed.value * clampedDelta;
|
|
115
140
|
|
|
116
141
|
// Canvas-confetti tilt animation (creates 3D tumbling effect)
|
|
117
|
-
tiltAngle.value += 0.1;
|
|
142
|
+
tiltAngle.value += 0.1 * clampedDelta;
|
|
118
143
|
tiltSin.value = Math.sin(tiltAngle.value);
|
|
119
144
|
tiltCos.value = Math.cos(tiltAngle.value);
|
|
120
145
|
random.value = Math.random() + 2;
|
|
121
146
|
|
|
122
|
-
// Update tick for progressive opacity fade
|
|
123
|
-
|
|
147
|
+
// Update tick for progressive opacity fade (time-based, not frame-based)
|
|
148
|
+
// Use elapsed time instead of frame count for frame-rate independence
|
|
149
|
+
const progress = Math.min(1, elapsed / duration);
|
|
150
|
+
tick.value = progress * totalTicks.value;
|
|
124
151
|
|
|
125
152
|
// Canvas-confetti progressive fade: opacity decreases linearly over lifetime
|
|
126
|
-
const progress = Math.min(1, tick.value / totalTicks.value);
|
|
127
153
|
opacity.value = 1 - progress;
|
|
128
154
|
});
|
|
129
155
|
|