partycles 0.3.0 → 0.4.0
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/dist/animations/animations/bees.d.ts +8 -0
- package/dist/animations/animations/bees.d.ts.map +1 -0
- package/dist/animations/animations/butterflies.d.ts +8 -0
- package/dist/animations/animations/butterflies.d.ts.map +1 -0
- package/dist/animations/animations/candy.d.ts +8 -0
- package/dist/animations/animations/candy.d.ts.map +1 -0
- package/dist/animations/animations/champagne.d.ts +8 -0
- package/dist/animations/animations/champagne.d.ts.map +1 -0
- package/dist/animations/animations/crystals.d.ts +8 -0
- package/dist/animations/animations/crystals.d.ts.map +1 -0
- package/dist/animations/animations/dandelion.d.ts +8 -0
- package/dist/animations/animations/dandelion.d.ts.map +1 -0
- package/dist/animations/animations/dice.d.ts +8 -0
- package/dist/animations/animations/dice.d.ts.map +1 -0
- package/dist/animations/animations/donuts.d.ts +8 -0
- package/dist/animations/animations/donuts.d.ts.map +1 -0
- package/dist/animations/animations/dragons.d.ts +8 -0
- package/dist/animations/animations/dragons.d.ts.map +1 -0
- package/dist/animations/animations/galaxy.d.ts.map +1 -1
- package/dist/animations/animations/ghosts.d.ts +8 -0
- package/dist/animations/animations/ghosts.d.ts.map +1 -0
- package/dist/animations/animations/glitch.d.ts +8 -0
- package/dist/animations/animations/glitch.d.ts.map +1 -0
- package/dist/animations/animations/index.d.ts.map +1 -1
- package/dist/animations/animations/leaves.d.ts +8 -0
- package/dist/animations/animations/leaves.d.ts.map +1 -0
- package/dist/animations/animations/levelup.d.ts +8 -0
- package/dist/animations/animations/levelup.d.ts.map +1 -0
- package/dist/animations/animations/magicdust.d.ts +8 -0
- package/dist/animations/animations/magicdust.d.ts.map +1 -0
- package/dist/animations/animations/matrix.d.ts +8 -0
- package/dist/animations/animations/matrix.d.ts.map +1 -0
- package/dist/animations/animations/music.d.ts.map +1 -1
- package/dist/animations/animations/pixels.d.ts +8 -0
- package/dist/animations/animations/pixels.d.ts.map +1 -0
- package/dist/animations/animations/pizza.d.ts +8 -0
- package/dist/animations/animations/pizza.d.ts.map +1 -0
- package/dist/animations/animations/popcorn.d.ts +8 -0
- package/dist/animations/animations/popcorn.d.ts.map +1 -0
- package/dist/animations/animations/rain.d.ts +8 -0
- package/dist/animations/animations/rain.d.ts.map +1 -0
- package/dist/animations/animations/runes.d.ts +8 -0
- package/dist/animations/animations/runes.d.ts.map +1 -0
- package/dist/animations/bees.d.ts +8 -0
- package/dist/animations/bees.d.ts.map +1 -0
- package/dist/animations/bubbles.esm.js +3 -3
- package/dist/animations/bubbles.esm.js.map +1 -1
- package/dist/animations/bubbles.js +3 -3
- package/dist/animations/bubbles.js.map +1 -1
- package/dist/animations/butterflies.d.ts +8 -0
- package/dist/animations/butterflies.d.ts.map +1 -0
- package/dist/animations/candy.d.ts +8 -0
- package/dist/animations/candy.d.ts.map +1 -0
- package/dist/animations/champagne.d.ts +8 -0
- package/dist/animations/champagne.d.ts.map +1 -0
- package/dist/animations/confetti.esm.js +1 -1
- package/dist/animations/confetti.esm.js.map +1 -1
- package/dist/animations/confetti.js +1 -1
- package/dist/animations/confetti.js.map +1 -1
- package/dist/animations/crystals.d.ts +8 -0
- package/dist/animations/crystals.d.ts.map +1 -0
- package/dist/animations/dandelion.d.ts +8 -0
- package/dist/animations/dandelion.d.ts.map +1 -0
- package/dist/animations/dice.d.ts +8 -0
- package/dist/animations/dice.d.ts.map +1 -0
- package/dist/animations/donuts.d.ts +8 -0
- package/dist/animations/donuts.d.ts.map +1 -0
- package/dist/animations/dragons.d.ts +8 -0
- package/dist/animations/dragons.d.ts.map +1 -0
- package/dist/animations/emoji.esm.js.map +1 -1
- package/dist/animations/emoji.js.map +1 -1
- package/dist/animations/fireworks.esm.js +1 -1
- package/dist/animations/fireworks.esm.js.map +1 -1
- package/dist/animations/fireworks.js +1 -1
- package/dist/animations/fireworks.js.map +1 -1
- package/dist/animations/galaxy.d.ts.map +1 -1
- package/dist/animations/ghosts.d.ts +8 -0
- package/dist/animations/ghosts.d.ts.map +1 -0
- package/dist/animations/glitch.d.ts +8 -0
- package/dist/animations/glitch.d.ts.map +1 -0
- package/dist/animations/hearts.esm.js +1 -1
- package/dist/animations/hearts.esm.js.map +1 -1
- package/dist/animations/hearts.js +1 -1
- package/dist/animations/hearts.js.map +1 -1
- package/dist/animations/leaves.d.ts +8 -0
- package/dist/animations/leaves.d.ts.map +1 -0
- package/dist/animations/levelup.d.ts +8 -0
- package/dist/animations/levelup.d.ts.map +1 -0
- package/dist/animations/magicdust.d.ts +8 -0
- package/dist/animations/magicdust.d.ts.map +1 -0
- package/dist/animations/matrix.d.ts +8 -0
- package/dist/animations/matrix.d.ts.map +1 -0
- package/dist/animations/music.d.ts.map +1 -1
- package/dist/animations/pixels.d.ts +8 -0
- package/dist/animations/pixels.d.ts.map +1 -0
- package/dist/animations/pizza.d.ts +8 -0
- package/dist/animations/pizza.d.ts.map +1 -0
- package/dist/animations/popcorn.d.ts +8 -0
- package/dist/animations/popcorn.d.ts.map +1 -0
- package/dist/animations/rain.d.ts +8 -0
- package/dist/animations/rain.d.ts.map +1 -0
- package/dist/animations/runes.d.ts +8 -0
- package/dist/animations/runes.d.ts.map +1 -0
- package/dist/animations/snow.esm.js +1 -1
- package/dist/animations/snow.esm.js.map +1 -1
- package/dist/animations/snow.js +1 -1
- package/dist/animations/snow.js.map +1 -1
- package/dist/animations/sparkles.esm.js +1 -1
- package/dist/animations/sparkles.esm.js.map +1 -1
- package/dist/animations/sparkles.js +1 -1
- package/dist/animations/sparkles.js.map +1 -1
- package/dist/animations/stars.esm.js +1 -1
- package/dist/animations/stars.esm.js.map +1 -1
- package/dist/animations/stars.js +1 -1
- package/dist/animations/stars.js.map +1 -1
- package/dist/animations/types.d.ts +1 -1
- package/dist/animations/types.d.ts.map +1 -1
- package/dist/index.esm.js +1423 -92
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1423 -92
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
@@ -13,7 +13,7 @@ const generateId = () => {
|
|
13
13
|
return Math.random().toString(36).substring(2, 9);
|
14
14
|
};
|
15
15
|
const getRandomColor = (colors) => {
|
16
|
-
return colors[Math.floor(Math.random() * colors.length)] || colors[0];
|
16
|
+
return colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff';
|
17
17
|
};
|
18
18
|
const createParticleStyle = (particle, containerRect) => {
|
19
19
|
return {
|
@@ -28,9 +28,9 @@ const createParticleStyle = (particle, containerRect) => {
|
|
28
28
|
};
|
29
29
|
};
|
30
30
|
|
31
|
-
const defaultColors = ['#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5', '#2196f3', '#03a9f4', '#00bcd4', '#009688', '#4caf50', '#8bc34a', '#cddc39', '#ffeb3b', '#ffc107', '#ff9800', '#ff5722'];
|
31
|
+
const defaultColors$f = ['#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5', '#2196f3', '#03a9f4', '#00bcd4', '#009688', '#4caf50', '#8bc34a', '#cddc39', '#ffeb3b', '#ffc107', '#ff9800', '#ff5722'];
|
32
32
|
const createConfettiParticles = (origin, config) => {
|
33
|
-
const { particleCount = 50, startVelocity = 20, colors = defaultColors, elementSize = 20 } = config;
|
33
|
+
const { particleCount = 50, startVelocity = 20, colors = defaultColors$f, elementSize = 20 } = config;
|
34
34
|
const particles = [];
|
35
35
|
for (let i = 0; i < particleCount; i++) {
|
36
36
|
const angle = randomInRange(0, 360);
|
@@ -76,7 +76,7 @@ const createSparkleParticles = (origin, config) => {
|
|
76
76
|
opacity: 0,
|
77
77
|
size: randomInRange(elementSize * 0.4, elementSize * 1.2),
|
78
78
|
rotation: randomInRange(0, 360),
|
79
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
79
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
80
80
|
});
|
81
81
|
}
|
82
82
|
return particles;
|
@@ -168,13 +168,13 @@ const createBubbleParticles = (origin, config) => {
|
|
168
168
|
id: generateId(),
|
169
169
|
x: origin.x + randomInRange(-spread, spread),
|
170
170
|
y: origin.y,
|
171
|
-
vx: randomInRange(-
|
172
|
-
vy: -randomInRange(startVelocity * 0.
|
171
|
+
vx: randomInRange(-3, 3),
|
172
|
+
vy: -randomInRange(startVelocity * 0.7, startVelocity * 1.2),
|
173
173
|
life: config.lifetime || 160,
|
174
174
|
opacity: 0.7,
|
175
175
|
size: randomInRange(elementSize * 0.4, elementSize * 1.2),
|
176
176
|
rotation: 0,
|
177
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
177
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
178
178
|
});
|
179
179
|
}
|
180
180
|
return particles;
|
@@ -211,7 +211,7 @@ const createStarParticles = (origin, config) => {
|
|
211
211
|
opacity: 1,
|
212
212
|
size: randomInRange(elementSize * 0.5, elementSize * 1.3),
|
213
213
|
rotation: randomInRange(0, 360),
|
214
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
214
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
215
215
|
});
|
216
216
|
}
|
217
217
|
return particles;
|
@@ -241,7 +241,7 @@ const createSnowParticles = (origin, config) => {
|
|
241
241
|
opacity: randomInRange(0.4, 0.9),
|
242
242
|
size: randomInRange(elementSize * 0.3, elementSize),
|
243
243
|
rotation: randomInRange(0, 360),
|
244
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
244
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
245
245
|
});
|
246
246
|
}
|
247
247
|
return particles;
|
@@ -324,7 +324,7 @@ const createCoinParticles = (origin, config) => {
|
|
324
324
|
opacity: 1,
|
325
325
|
size: randomInRange(elementSize * 0.8, elementSize * 1.2),
|
326
326
|
rotation: randomInRange(0, 360),
|
327
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
327
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
328
328
|
});
|
329
329
|
}
|
330
330
|
return particles;
|
@@ -378,7 +378,7 @@ const createLightningParticles = (origin, config) => {
|
|
378
378
|
opacity: 1,
|
379
379
|
size: randomInRange(elementSize * 0.5, elementSize * 1.5),
|
380
380
|
rotation: randomInRange(0, 360),
|
381
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
381
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
382
382
|
});
|
383
383
|
}
|
384
384
|
return particles;
|
@@ -433,7 +433,7 @@ const createPetalParticles = (origin, config) => {
|
|
433
433
|
opacity: randomInRange(0.7, 1),
|
434
434
|
size: randomInRange(elementSize * 0.7, elementSize * 1.3),
|
435
435
|
rotation: randomInRange(0, 360),
|
436
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
436
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
437
437
|
});
|
438
438
|
}
|
439
439
|
return particles;
|
@@ -491,7 +491,7 @@ const createAuroraParticles = (origin, config) => {
|
|
491
491
|
opacity: 0,
|
492
492
|
size: randomInRange(elementSize * 0.8, elementSize * 1.2),
|
493
493
|
rotation: randomInRange(-15, 15),
|
494
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
494
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
495
495
|
});
|
496
496
|
}
|
497
497
|
return particles;
|
@@ -548,7 +548,7 @@ const createFireflyParticles = (origin, config) => {
|
|
548
548
|
opacity: 0,
|
549
549
|
size: randomInRange(elementSize * 0.6, elementSize),
|
550
550
|
rotation: randomInRange(0, 360), // Used for blink timing
|
551
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
551
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
552
552
|
});
|
553
553
|
}
|
554
554
|
return particles;
|
@@ -618,7 +618,7 @@ const createPaintParticles = (origin, config) => {
|
|
618
618
|
? randomInRange(elementSize * 1.5, elementSize * 2.5)
|
619
619
|
: randomInRange(elementSize * 0.3, elementSize),
|
620
620
|
rotation: randomInRange(0, 360),
|
621
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
621
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
622
622
|
});
|
623
623
|
}
|
624
624
|
return particles;
|
@@ -699,7 +699,7 @@ const createMusicParticles = (origin, config) => {
|
|
699
699
|
opacity: 1,
|
700
700
|
size: randomInRange(elementSize * 0.8, elementSize * 1.2),
|
701
701
|
rotation: i % notes.length, // Store which note to use
|
702
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
702
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
703
703
|
});
|
704
704
|
}
|
705
705
|
return particles;
|
@@ -710,9 +710,13 @@ const renderMusicParticle = (particle) => {
|
|
710
710
|
// Wave motion as notes float up
|
711
711
|
const waveX = Math.sin(particle.life * 0.05) * 20;
|
712
712
|
const wobble = Math.sin(particle.life * 0.1) * 10;
|
713
|
-
//
|
714
|
-
|
715
|
-
const
|
713
|
+
// Simple fade based on particle life
|
714
|
+
// Assume default lifetime of 300 if not set
|
715
|
+
const totalLife = 300;
|
716
|
+
const age = totalLife - particle.life; // How old the particle is
|
717
|
+
// Fade in during first 20 frames
|
718
|
+
const fadeIn = age < 20 ? age / 20 : 1;
|
719
|
+
// Fade out during last 50 frames
|
716
720
|
const fadeOut = particle.life < 50 ? particle.life / 50 : 1;
|
717
721
|
const opacity = Math.min(fadeIn, fadeOut) * particle.opacity;
|
718
722
|
return (React.createElement("div", { key: particle.id, style: {
|
@@ -764,15 +768,15 @@ const createBalloonParticles = (origin, config) => {
|
|
764
768
|
const velocity = randomInRange(startVelocity * 0.7, startVelocity);
|
765
769
|
particles.push({
|
766
770
|
id: generateId(),
|
767
|
-
x: origin.x + randomInRange(-
|
768
|
-
y: origin.y + randomInRange(
|
769
|
-
vx: Math.sin(angle) * velocity * 0.
|
771
|
+
x: origin.x + randomInRange(-spread * 0.8, spread * 0.8), // Spread balloons out more
|
772
|
+
y: origin.y + randomInRange(-10, 30),
|
773
|
+
vx: Math.sin(angle) * velocity * 0.3 + randomInRange(-1, 1), // Add horizontal drift
|
770
774
|
vy: -velocity * 0.4, // Balloons float up slowly
|
771
775
|
life: config.lifetime || 250,
|
772
776
|
opacity: 0.9,
|
773
777
|
size: randomInRange(elementSize * 0.8, elementSize * 1.2),
|
774
778
|
rotation: randomInRange(-10, 10),
|
775
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
779
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
776
780
|
});
|
777
781
|
}
|
778
782
|
return particles;
|
@@ -868,7 +872,7 @@ const createGalaxyParticles = (origin, config) => {
|
|
868
872
|
opacity: 0,
|
869
873
|
size: randomInRange(elementSize * 0.3, elementSize) * (1 - progress * 0.5), // Smaller at edges
|
870
874
|
rotation: randomInRange(0, 360),
|
871
|
-
color: colors[Math.floor(Math.random() * colors.length)] || colors[0],
|
875
|
+
color: colors[Math.floor(Math.random() * colors.length)] || colors[0] || '#ffffff',
|
872
876
|
});
|
873
877
|
}
|
874
878
|
return particles;
|
@@ -936,74 +940,1401 @@ const renderGalaxyParticle = (particle) => {
|
|
936
940
|
} }))));
|
937
941
|
};
|
938
942
|
|
939
|
-
const
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
}
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
943
|
+
const matrixChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン';
|
944
|
+
const createMatrixParticles = (origin, config) => {
|
945
|
+
const { particleCount = 50, elementSize = 300 } = config;
|
946
|
+
const particles = [];
|
947
|
+
const columns = Math.floor(elementSize / 20);
|
948
|
+
for (let i = 0; i < columns; i++) {
|
949
|
+
const columnX = origin.x - elementSize / 2 + (i / columns) * elementSize;
|
950
|
+
const columnParticles = Math.floor(Math.random() * 15) + 10;
|
951
|
+
for (let j = 0; j < columnParticles; j++) {
|
952
|
+
const charIndex = Math.floor(Math.random() * matrixChars.length);
|
953
|
+
const speed = randomInRange(80, 120);
|
954
|
+
particles.push({
|
955
|
+
id: generateId(),
|
956
|
+
x: columnX + randomInRange(-10, 10),
|
957
|
+
y: origin.y - elementSize / 2 - j * 25 - randomInRange(0, 100),
|
958
|
+
vx: columnParticles, // Store columnHeight in vx (since we don't use horizontal movement)
|
959
|
+
vy: speed,
|
960
|
+
life: config.lifetime || 150,
|
961
|
+
opacity: 1,
|
962
|
+
size: 20 + (j * 0.1), // Store fadeDelay as decimal part
|
963
|
+
rotation: charIndex + (columnParticles * 1000), // Store charIndex and columnHeight
|
964
|
+
color: '#00ff00',
|
965
|
+
});
|
966
|
+
}
|
967
|
+
}
|
968
|
+
return particles.slice(0, particleCount);
|
969
|
+
};
|
970
|
+
const renderMatrixParticle = (particle) => {
|
971
|
+
// Extract stored values
|
972
|
+
const charIndex = Math.floor(particle.rotation % 1000);
|
973
|
+
const columnHeight = Math.floor(particle.rotation / 1000);
|
974
|
+
const fadeDelay = (particle.size - Math.floor(particle.size));
|
975
|
+
const character = matrixChars[charIndex] || matrixChars[0];
|
976
|
+
const brightness = 1 - (fadeDelay / columnHeight) * 0.5;
|
977
|
+
return (React.createElement("div", { key: particle.id, style: {
|
978
|
+
fontSize: '20px',
|
979
|
+
fontFamily: 'monospace',
|
980
|
+
fontWeight: 'bold',
|
981
|
+
color: `rgba(${0}, ${255 * brightness}, ${0}, ${particle.opacity})`,
|
982
|
+
textShadow: `0 0 10px rgba(0, ${255 * brightness}, 0, ${particle.opacity * 0.8})`,
|
983
|
+
userSelect: 'none',
|
984
|
+
} }, character));
|
985
|
+
};
|
986
|
+
|
987
|
+
const pixelColors = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF', '#FFA500', '#FF1493'];
|
988
|
+
const createPixelParticles = (origin, config) => {
|
989
|
+
const { particleCount = 30, colors = pixelColors, elementSize = 20 } = config;
|
990
|
+
const particles = [];
|
991
|
+
const gridSize = Math.floor(Math.sqrt(particleCount));
|
992
|
+
const spacing = 30;
|
993
|
+
for (let i = 0; i < gridSize; i++) {
|
994
|
+
for (let j = 0; j < gridSize; j++) {
|
995
|
+
const targetX = origin.x + (i - gridSize / 2) * spacing;
|
996
|
+
const targetY = origin.y + (j - gridSize / 2) * spacing;
|
997
|
+
const angle = randomInRange(0, 360);
|
998
|
+
const velocity = randomInRange(150, 300);
|
999
|
+
particles.push({
|
1000
|
+
id: generateId(),
|
1001
|
+
x: targetX,
|
1002
|
+
y: targetY,
|
1003
|
+
vx: Math.cos(degreesToRadians(angle)) * velocity,
|
1004
|
+
vy: Math.sin(degreesToRadians(angle)) * velocity,
|
1005
|
+
life: config.lifetime || 150,
|
1006
|
+
opacity: 1,
|
1007
|
+
size: randomInRange(elementSize * 0.6, elementSize),
|
1008
|
+
// Store targetX offset in rotation (from -500 to 500, add 1000 to make positive)
|
1009
|
+
rotation: ((targetX - origin.x) + 500) + ((targetY - origin.y) + 500) * 1000,
|
1010
|
+
color: getRandomColor(colors),
|
1011
|
+
});
|
1012
|
+
}
|
1013
|
+
}
|
1014
|
+
return particles.slice(0, particleCount);
|
1015
|
+
};
|
1016
|
+
const renderPixelParticle = (particle) => {
|
1017
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1018
|
+
width: `${particle.size}px`,
|
1019
|
+
height: `${particle.size}px`,
|
1020
|
+
backgroundColor: particle.color,
|
1021
|
+
boxShadow: `0 0 ${particle.size / 2}px ${particle.color}`,
|
1022
|
+
} }));
|
1023
|
+
};
|
1024
|
+
|
1025
|
+
const createGlitchParticles = (origin, config) => {
|
1026
|
+
const { particleCount = 20, elementSize = 200 } = config;
|
1027
|
+
const particles = [];
|
1028
|
+
const channels = ['r', 'g', 'b'];
|
1029
|
+
for (let i = 0; i < particleCount; i++) {
|
1030
|
+
const isHorizontal = Math.random() > 0.3;
|
1031
|
+
const channelIndex = i % 3;
|
1032
|
+
const channel = channels[channelIndex];
|
1033
|
+
// Encode all data in rotation:
|
1034
|
+
// bits 0-1: channel (0=r, 1=g, 2=b)
|
1035
|
+
// bit 2: isHorizontal (0=false, 1=true)
|
1036
|
+
// bits 3-10: width (0-255)
|
1037
|
+
// bits 11-18: height (0-255)
|
1038
|
+
// bits 19-24: glitchOffset + 32 (to make positive)
|
1039
|
+
const width = isHorizontal ? randomInRange(50, 200) : randomInRange(2, 8);
|
1040
|
+
const height = isHorizontal ? randomInRange(2, 8) : randomInRange(50, 200);
|
1041
|
+
const glitchOffset = randomInRange(-20, 20);
|
1042
|
+
const encodedData = channelIndex +
|
1043
|
+
(isHorizontal ? 4 : 0) +
|
1044
|
+
(Math.floor(width) << 3) +
|
1045
|
+
(Math.floor(height) << 11) +
|
1046
|
+
((glitchOffset + 32) << 19);
|
1047
|
+
particles.push({
|
1048
|
+
id: generateId(),
|
1049
|
+
x: origin.x + randomInRange(-elementSize / 2, elementSize / 2),
|
1050
|
+
y: origin.y + randomInRange(-elementSize / 2, elementSize / 2),
|
1051
|
+
vx: randomInRange(-50, 50),
|
1052
|
+
vy: randomInRange(-30, 30),
|
1053
|
+
life: config.lifetime || 150,
|
1054
|
+
opacity: randomInRange(0.3, 1),
|
1055
|
+
size: randomInRange(5, 20), // Store distortionAmount
|
1056
|
+
rotation: encodedData,
|
1057
|
+
color: channel === 'r' ? '#ff0000' : channel === 'g' ? '#00ff00' : '#0000ff',
|
1058
|
+
});
|
1059
|
+
}
|
1060
|
+
return particles;
|
1061
|
+
};
|
1062
|
+
const renderGlitchParticle = (particle) => {
|
1063
|
+
// Decode data from rotation
|
1064
|
+
const channelIndex = particle.rotation & 3;
|
1065
|
+
const width = (particle.rotation >> 3) & 255;
|
1066
|
+
const height = (particle.rotation >> 11) & 255;
|
1067
|
+
const glitchOffset = ((particle.rotation >> 19) & 63) - 32;
|
1068
|
+
const channel = ['r', 'g', 'b'][channelIndex];
|
1069
|
+
const distortionAmount = particle.size;
|
1070
|
+
const colors = {
|
1071
|
+
r: channel === 'r' ? 255 : 0,
|
1072
|
+
g: channel === 'g' ? 255 : 0,
|
1073
|
+
b: channel === 'b' ? 255 : 0,
|
1074
|
+
};
|
1075
|
+
const mixBlendMode = channel === 'r' ? 'screen' :
|
1076
|
+
channel === 'g' ? 'multiply' : 'difference';
|
1077
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1078
|
+
width: `${width}px`,
|
1079
|
+
height: `${height}px`,
|
1080
|
+
backgroundColor: `rgba(${colors.r}, ${colors.g}, ${colors.b}, ${particle.opacity})`,
|
1081
|
+
mixBlendMode,
|
1082
|
+
filter: `blur(${randomInRange(0, 2)}px)`,
|
1083
|
+
boxShadow: `${glitchOffset}px 0 ${distortionAmount}px rgba(${colors.r}, ${colors.g}, ${colors.b}, ${particle.opacity * 0.5})`,
|
1084
|
+
} }));
|
1085
|
+
};
|
1086
|
+
|
1087
|
+
const getDiceFace = (value) => {
|
1088
|
+
const faces = ['⚀', '⚁', '⚂', '⚃', '⚄', '⚅'];
|
1089
|
+
return faces[value - 1] || '⚀';
|
1090
|
+
};
|
1091
|
+
const createDiceParticles = (origin, config) => {
|
1092
|
+
const { particleCount = 8, startVelocity = 25, elementSize = 40 } = config;
|
1093
|
+
const particles = [];
|
1094
|
+
for (let i = 0; i < particleCount; i++) {
|
1095
|
+
const angle = randomInRange(0, 360);
|
1096
|
+
const velocity = randomInRange(startVelocity * 0.5, startVelocity);
|
1097
|
+
const diceValue = Math.floor(randomInRange(1, 7));
|
1098
|
+
particles.push({
|
1099
|
+
id: generateId(),
|
1100
|
+
x: origin.x,
|
1101
|
+
y: origin.y,
|
1102
|
+
vx: Math.cos(degreesToRadians(angle)) * velocity,
|
1103
|
+
vy: Math.sin(degreesToRadians(angle)) * velocity - 30,
|
1104
|
+
life: config.lifetime || 150,
|
1105
|
+
opacity: 1,
|
1106
|
+
size: randomInRange(elementSize * 0.8, elementSize * 1.2),
|
1107
|
+
// Store dice value (1-6) in lower bits, and rotation angles in upper bits
|
1108
|
+
rotation: diceValue + (Math.floor(randomInRange(0, 360)) * 10),
|
1109
|
+
color: '#ffffff',
|
1110
|
+
});
|
1111
|
+
}
|
1112
|
+
return particles;
|
1113
|
+
};
|
1114
|
+
const renderDiceParticle = (particle) => {
|
1115
|
+
const diceValue = particle.rotation % 10;
|
1116
|
+
const rotationAngle = Math.floor(particle.rotation / 10);
|
1117
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1118
|
+
width: `${particle.size}px`,
|
1119
|
+
height: `${particle.size}px`,
|
1120
|
+
fontSize: `${particle.size * 0.8}px`,
|
1121
|
+
display: 'flex',
|
1122
|
+
alignItems: 'center',
|
1123
|
+
justifyContent: 'center',
|
1124
|
+
backgroundColor: '#fff',
|
1125
|
+
color: '#000',
|
1126
|
+
borderRadius: `${particle.size * 0.2}px`,
|
1127
|
+
transform: `rotate(${rotationAngle}deg)`,
|
1128
|
+
transformStyle: 'preserve-3d',
|
1129
|
+
boxShadow: '0 4px 8px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.5)',
|
1130
|
+
border: '2px solid #333',
|
1131
|
+
fontWeight: 'bold',
|
1132
|
+
} }, getDiceFace(diceValue)));
|
1133
|
+
};
|
1134
|
+
|
1135
|
+
const levelUpTexts = ['+1', '+10', '+100', 'XP', '+XP', 'LEVEL UP!', 'CRITICAL!', 'COMBO!', 'PERFECT!'];
|
1136
|
+
const levelUpColors = [
|
1137
|
+
{ text: '#FFD700', glow: '#FFA500' }, // Gold
|
1138
|
+
{ text: '#00FF00', glow: '#00AA00' }, // Green
|
1139
|
+
{ text: '#00FFFF', glow: '#0088FF' }, // Cyan
|
1140
|
+
{ text: '#FF00FF', glow: '#AA00AA' }, // Magenta
|
1141
|
+
{ text: '#FFFF00', glow: '#FFAA00' }, // Yellow
|
1142
|
+
];
|
1143
|
+
const createLevelUpParticles = (origin, config) => {
|
1144
|
+
const { particleCount = 10, startVelocity = 20, elementSize = 30 } = config;
|
1145
|
+
const particles = [];
|
1146
|
+
for (let i = 0; i < particleCount; i++) {
|
1147
|
+
const angle = randomInRange(-45, 45);
|
1148
|
+
const velocity = randomInRange(startVelocity * 0.5, startVelocity * 1.5);
|
1149
|
+
const colorSetIndex = Math.floor(Math.random() * levelUpColors.length);
|
1150
|
+
const colorSet = levelUpColors[colorSetIndex] || levelUpColors[0];
|
1151
|
+
const textIndex = Math.floor(Math.random() * levelUpTexts.length);
|
1152
|
+
const text = levelUpTexts[textIndex];
|
1153
|
+
const isMainText = text === 'LEVEL UP!' || text === 'CRITICAL!';
|
1154
|
+
const fontSize = isMainText ? randomInRange(elementSize * 1.3, elementSize * 2) : randomInRange(elementSize * 0.7, elementSize * 1.2);
|
1155
|
+
particles.push({
|
1156
|
+
id: generateId(),
|
1157
|
+
x: origin.x,
|
1158
|
+
y: origin.y,
|
1159
|
+
vx: Math.sin(degreesToRadians(angle)) * velocity,
|
1160
|
+
vy: -Math.cos(degreesToRadians(angle)) * velocity - 10,
|
1161
|
+
life: config.lifetime || 150,
|
1162
|
+
opacity: 1,
|
1163
|
+
size: fontSize, // Store fontSize in size
|
1164
|
+
// Store textIndex (0-8) + colorSetIndex (0-4) * 10 + delay (0-50) * 100
|
1165
|
+
rotation: textIndex + (colorSetIndex * 10) + (Math.floor(i * 5) * 100),
|
1166
|
+
color: colorSet.text,
|
1167
|
+
});
|
1168
|
+
}
|
1169
|
+
return particles;
|
1170
|
+
};
|
1171
|
+
const renderLevelUpParticle = (particle) => {
|
1172
|
+
// Extract encoded values
|
1173
|
+
const textIndex = particle.rotation % 10;
|
1174
|
+
const colorSetIndex = Math.floor((particle.rotation % 100) / 10);
|
1175
|
+
const delay = Math.floor(particle.rotation / 100) / 100;
|
1176
|
+
const text = levelUpTexts[textIndex] || levelUpTexts[0];
|
1177
|
+
const colorSet = levelUpColors[colorSetIndex] || levelUpColors[0];
|
1178
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1179
|
+
fontSize: `${particle.size}px`,
|
1180
|
+
fontWeight: 'bold',
|
1181
|
+
fontFamily: 'Arial, sans-serif',
|
1182
|
+
color: particle.color,
|
1183
|
+
textShadow: `
|
1184
|
+
0 0 10px ${colorSet.glow},
|
1185
|
+
0 0 20px ${colorSet.glow},
|
1186
|
+
0 0 30px ${particle.color},
|
1187
|
+
0 2px 4px rgba(0,0,0,0.5)
|
1188
|
+
`,
|
1189
|
+
letterSpacing: '2px',
|
1190
|
+
textTransform: 'uppercase',
|
1191
|
+
whiteSpace: 'nowrap',
|
1192
|
+
userSelect: 'none',
|
1193
|
+
animationDelay: `${delay}s`,
|
1194
|
+
} }, text));
|
1195
|
+
};
|
1196
|
+
|
1197
|
+
const defaultColors$e = ['#9C27B0', '#E91E63', '#FF00FF', '#00FFFF', '#FFD700', '#FF69B4', '#DA70D6', '#9370DB'];
|
1198
|
+
const createMagicDustParticles = (origin, config) => {
|
1199
|
+
const { particleCount = 40, startVelocity = 8, colors = defaultColors$e, elementSize = 12 } = config;
|
1200
|
+
const particles = [];
|
1201
|
+
for (let i = 0; i < particleCount; i++) {
|
1202
|
+
// Create particles in a circular pattern with some randomness
|
1203
|
+
const angle = (i / particleCount) * 360 + randomInRange(-30, 30);
|
1204
|
+
const velocity = randomInRange(startVelocity * 0.3, startVelocity);
|
1205
|
+
const color = getRandomColor(colors);
|
1206
|
+
// Add some particles that trail behind cursor movement
|
1207
|
+
const offsetAngle = randomInRange(0, 360);
|
1208
|
+
const offsetDistance = randomInRange(0, 30);
|
1209
|
+
particles.push({
|
1210
|
+
id: generateId(),
|
1211
|
+
x: origin.x + Math.cos(degreesToRadians(offsetAngle)) * offsetDistance,
|
1212
|
+
y: origin.y + Math.sin(degreesToRadians(offsetAngle)) * offsetDistance,
|
1213
|
+
vx: Math.cos(degreesToRadians(angle)) * velocity + randomInRange(-2, 2),
|
1214
|
+
vy: Math.sin(degreesToRadians(angle)) * velocity + randomInRange(-2, 2),
|
1215
|
+
life: config.lifetime || 120,
|
1216
|
+
opacity: randomInRange(0.4, 1),
|
1217
|
+
size: randomInRange(elementSize * 0.3, elementSize),
|
1218
|
+
rotation: randomInRange(0, 360),
|
1219
|
+
color,
|
1220
|
+
});
|
1221
|
+
}
|
1222
|
+
return particles;
|
1223
|
+
};
|
1224
|
+
const renderMagicDustParticle = (particle) => {
|
1225
|
+
const sparkleSize = particle.size * 0.7;
|
1226
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1227
|
+
width: `${particle.size}px`,
|
1228
|
+
height: `${particle.size}px`,
|
1229
|
+
position: 'relative',
|
1230
|
+
} },
|
1231
|
+
React.createElement("div", { style: {
|
1232
|
+
position: 'absolute',
|
1233
|
+
width: '100%',
|
1234
|
+
height: '100%',
|
1235
|
+
backgroundColor: particle.color,
|
1236
|
+
borderRadius: '50%',
|
1237
|
+
boxShadow: `0 0 ${particle.size}px ${particle.color}, 0 0 ${particle.size * 2}px ${particle.color}`,
|
1238
|
+
filter: 'blur(1px)',
|
1239
|
+
} }),
|
1240
|
+
React.createElement("div", { style: {
|
1241
|
+
position: 'absolute',
|
1242
|
+
top: '50%',
|
1243
|
+
left: '50%',
|
1244
|
+
width: `${sparkleSize}px`,
|
1245
|
+
height: `${sparkleSize}px`,
|
1246
|
+
transform: `translate(-50%, -50%) rotate(${particle.rotation}deg)`,
|
1247
|
+
} },
|
1248
|
+
React.createElement("div", { style: {
|
1249
|
+
position: 'absolute',
|
1250
|
+
width: '100%',
|
1251
|
+
height: '2px',
|
1252
|
+
backgroundColor: 'white',
|
1253
|
+
top: '50%',
|
1254
|
+
left: '0',
|
1255
|
+
transform: 'translateY(-50%)',
|
1256
|
+
boxShadow: '0 0 4px white',
|
1257
|
+
} }),
|
1258
|
+
React.createElement("div", { style: {
|
1259
|
+
position: 'absolute',
|
1260
|
+
width: '2px',
|
1261
|
+
height: '100%',
|
1262
|
+
backgroundColor: 'white',
|
1263
|
+
left: '50%',
|
1264
|
+
top: '0',
|
1265
|
+
transform: 'translateX(-50%)',
|
1266
|
+
boxShadow: '0 0 4px white',
|
1267
|
+
} }))));
|
1268
|
+
};
|
1269
|
+
|
1270
|
+
const defaultColors$d = ['#FFFFFF', '#F0F0F0', '#E8E8E8', '#F5F5F5', '#FAFAFA'];
|
1271
|
+
const createGhostParticles = (origin, config) => {
|
1272
|
+
const { particleCount = 8, startVelocity = 5, colors = defaultColors$d, elementSize = 30 } = config;
|
1273
|
+
const particles = [];
|
1274
|
+
for (let i = 0; i < particleCount; i++) {
|
1275
|
+
// Ghosts float upward with slight horizontal movement
|
1276
|
+
const angle = randomInRange(250, 290); // Mostly upward
|
1277
|
+
const velocity = randomInRange(startVelocity * 0.5, startVelocity);
|
1278
|
+
const color = getRandomColor(colors);
|
1279
|
+
particles.push({
|
1280
|
+
id: generateId(),
|
1281
|
+
x: origin.x + randomInRange(-50, 50),
|
1282
|
+
y: origin.y + randomInRange(-20, 20),
|
1283
|
+
vx: Math.cos(degreesToRadians(angle)) * velocity,
|
1284
|
+
vy: Math.sin(degreesToRadians(angle)) * velocity,
|
1285
|
+
life: config.lifetime || 200,
|
1286
|
+
opacity: randomInRange(0.5, 0.8),
|
1287
|
+
size: randomInRange(elementSize * 0.8, elementSize * 1.2),
|
1288
|
+
rotation: randomInRange(-15, 15),
|
1289
|
+
color,
|
1290
|
+
});
|
1291
|
+
}
|
1292
|
+
return particles;
|
1293
|
+
};
|
1294
|
+
const renderGhostParticle = (particle) => {
|
1295
|
+
// Calculate wave effect for tail
|
1296
|
+
const waveOffset = Math.sin(Date.now() * 0.003 + particle.x * 0.01) * 3;
|
1297
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1298
|
+
width: `${particle.size}px`,
|
1299
|
+
height: `${particle.size * 1.4}px`,
|
1300
|
+
position: 'relative',
|
1301
|
+
transform: `rotate(${particle.rotation}deg)`,
|
1302
|
+
} },
|
1303
|
+
React.createElement("div", { style: {
|
1304
|
+
position: 'absolute',
|
1305
|
+
width: '100%',
|
1306
|
+
height: '70%',
|
1307
|
+
backgroundColor: particle.color,
|
1308
|
+
borderRadius: '50% 50% 0 0',
|
1309
|
+
boxShadow: `0 0 20px rgba(255, 255, 255, 0.5), inset 0 0 10px rgba(0, 0, 0, 0.1)`,
|
1310
|
+
} }),
|
1311
|
+
React.createElement("div", { style: {
|
1312
|
+
position: 'absolute',
|
1313
|
+
bottom: 0,
|
1314
|
+
width: '100%',
|
1315
|
+
height: '40%',
|
1316
|
+
backgroundColor: particle.color,
|
1317
|
+
clipPath: `polygon(
|
1318
|
+
0 0,
|
1319
|
+
100% 0,
|
1320
|
+
100% 60%,
|
1321
|
+
${75 + waveOffset}% 80%,
|
1322
|
+
${50 - waveOffset}% 100%,
|
1323
|
+
${25 + waveOffset}% 80%,
|
1324
|
+
0 60%
|
1325
|
+
)`,
|
1326
|
+
} }),
|
1327
|
+
React.createElement("div", { style: {
|
1328
|
+
position: 'absolute',
|
1329
|
+
top: '30%',
|
1330
|
+
left: '25%',
|
1331
|
+
width: '15%',
|
1332
|
+
height: '15%',
|
1333
|
+
backgroundColor: '#000',
|
1334
|
+
borderRadius: '50%',
|
1335
|
+
} }),
|
1336
|
+
React.createElement("div", { style: {
|
1337
|
+
position: 'absolute',
|
1338
|
+
top: '30%',
|
1339
|
+
right: '25%',
|
1340
|
+
width: '15%',
|
1341
|
+
height: '15%',
|
1342
|
+
backgroundColor: '#000',
|
1343
|
+
borderRadius: '50%',
|
1344
|
+
} }),
|
1345
|
+
React.createElement("div", { style: {
|
1346
|
+
position: 'absolute',
|
1347
|
+
top: '45%',
|
1348
|
+
left: '50%',
|
1349
|
+
transform: 'translateX(-50%)',
|
1350
|
+
width: '25%',
|
1351
|
+
height: '15%',
|
1352
|
+
border: '2px solid #000',
|
1353
|
+
borderTop: 'none',
|
1354
|
+
borderRadius: '0 0 50% 50%',
|
1355
|
+
} })));
|
1356
|
+
};
|
1357
|
+
|
1358
|
+
const defaultColors$c = ['#FF1493', '#00CED1', '#FFD700', '#FF69B4', '#7B68EE', '#00FA9A', '#FF6347', '#4169E1'];
|
1359
|
+
const createCrystalParticles = (origin, config) => {
|
1360
|
+
const { particleCount = 15, startVelocity = 15, colors = defaultColors$c, elementSize = 25 } = config;
|
1361
|
+
const particles = [];
|
1362
|
+
for (let i = 0; i < particleCount; i++) {
|
1363
|
+
// Crystals explode outward and fall with gravity
|
1364
|
+
const angle = randomInRange(0, 360);
|
1365
|
+
const velocity = randomInRange(startVelocity * 0.5, startVelocity);
|
1366
|
+
const color = getRandomColor(colors);
|
1367
|
+
particles.push({
|
1368
|
+
id: generateId(),
|
1369
|
+
x: origin.x,
|
1370
|
+
y: origin.y,
|
1371
|
+
vx: Math.cos(degreesToRadians(angle)) * velocity,
|
1372
|
+
vy: Math.sin(degreesToRadians(angle)) * velocity - 10,
|
1373
|
+
life: config.lifetime || 150,
|
1374
|
+
opacity: randomInRange(0.7, 1),
|
1375
|
+
size: randomInRange(elementSize * 0.6, elementSize),
|
1376
|
+
rotation: randomInRange(0, 360),
|
1377
|
+
color,
|
1378
|
+
});
|
1379
|
+
}
|
1380
|
+
return particles;
|
1381
|
+
};
|
1382
|
+
const renderCrystalParticle = (particle) => {
|
1383
|
+
// Create rainbow refraction effect
|
1384
|
+
const hue = (Date.now() * 0.5 + particle.x + particle.y) % 360;
|
1385
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1386
|
+
width: `${particle.size}px`,
|
1387
|
+
height: `${particle.size * 1.5}px`,
|
1388
|
+
position: 'relative',
|
1389
|
+
transform: `rotate(${particle.rotation}deg)`,
|
1390
|
+
} },
|
1391
|
+
React.createElement("div", { style: {
|
1392
|
+
position: 'absolute',
|
1393
|
+
width: '100%',
|
1394
|
+
height: '100%',
|
1395
|
+
background: `linear-gradient(135deg, ${particle.color}, ${particle.color}88, transparent)`,
|
1396
|
+
clipPath: 'polygon(50% 0%, 100% 40%, 75% 100%, 25% 100%, 0% 40%)',
|
1397
|
+
boxShadow: `0 0 ${particle.size}px ${particle.color}44`,
|
1398
|
+
} }),
|
1399
|
+
React.createElement("div", { style: {
|
1400
|
+
position: 'absolute',
|
1401
|
+
width: '80%',
|
1402
|
+
height: '80%',
|
1403
|
+
top: '10%',
|
1404
|
+
left: '10%',
|
1405
|
+
background: `linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.4), transparent)`,
|
1406
|
+
clipPath: 'polygon(50% 10%, 90% 45%, 65% 90%, 35% 90%, 10% 45%)',
|
1407
|
+
} }),
|
1408
|
+
React.createElement("div", { style: {
|
1409
|
+
position: 'absolute',
|
1410
|
+
width: '100%',
|
1411
|
+
height: '100%',
|
1412
|
+
background: `linear-gradient(${hue}deg,
|
1413
|
+
hsla(${hue}, 100%, 50%, 0.3),
|
1414
|
+
hsla(${(hue + 60) % 360}, 100%, 50%, 0.3),
|
1415
|
+
hsla(${(hue + 120) % 360}, 100%, 50%, 0.3)
|
1416
|
+
)`,
|
1417
|
+
clipPath: 'polygon(50% 0%, 100% 40%, 75% 100%, 25% 100%, 0% 40%)',
|
1418
|
+
mixBlendMode: 'screen',
|
1419
|
+
} }),
|
1420
|
+
React.createElement("div", { style: {
|
1421
|
+
position: 'absolute',
|
1422
|
+
width: '30%',
|
1423
|
+
height: '30%',
|
1424
|
+
top: '20%',
|
1425
|
+
left: '35%',
|
1426
|
+
background: 'radial-gradient(circle, rgba(255, 255, 255, 0.8), transparent)',
|
1427
|
+
borderRadius: '50%',
|
1428
|
+
filter: 'blur(2px)',
|
1429
|
+
} })));
|
1430
|
+
};
|
1431
|
+
|
1432
|
+
const defaultColors$b = ['#FF4500', '#DC143C', '#B22222', '#8B0000', '#FF6347', '#FF8C00'];
|
1433
|
+
const createDragonParticles = (origin, config) => {
|
1434
|
+
const { particleCount = 6, startVelocity = 12, colors = defaultColors$b, elementSize = 40 } = config;
|
1435
|
+
const particles = [];
|
1436
|
+
for (let i = 0; i < particleCount; i++) {
|
1437
|
+
// Dragons fly in various directions with swooping motion
|
1438
|
+
const angle = randomInRange(0, 360);
|
1439
|
+
const velocity = randomInRange(startVelocity * 0.7, startVelocity);
|
1440
|
+
const color = getRandomColor(colors);
|
1441
|
+
particles.push({
|
1442
|
+
id: generateId(),
|
1443
|
+
x: origin.x + randomInRange(-30, 30),
|
1444
|
+
y: origin.y + randomInRange(-30, 30),
|
1445
|
+
vx: Math.cos(degreesToRadians(angle)) * velocity,
|
1446
|
+
vy: Math.sin(degreesToRadians(angle)) * velocity,
|
1447
|
+
life: config.lifetime || 180,
|
1448
|
+
opacity: 1,
|
1449
|
+
size: randomInRange(elementSize * 0.8, elementSize),
|
1450
|
+
rotation: angle,
|
1451
|
+
color,
|
1452
|
+
});
|
1453
|
+
}
|
1454
|
+
return particles;
|
1455
|
+
};
|
1456
|
+
const renderDragonParticle = (particle) => {
|
1457
|
+
// Calculate wing flap animation
|
1458
|
+
const wingFlap = Math.sin(Date.now() * 0.01 + particle.x) * 10;
|
1459
|
+
// Calculate fire breath pulse
|
1460
|
+
const firePulse = (Math.sin(Date.now() * 0.005 + particle.y) + 1) / 2;
|
1461
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1462
|
+
width: `${particle.size}px`,
|
1463
|
+
height: `${particle.size}px`,
|
1464
|
+
position: 'relative',
|
1465
|
+
transform: `rotate(${particle.rotation}deg)`,
|
1466
|
+
} },
|
1467
|
+
React.createElement("div", { style: {
|
1468
|
+
position: 'absolute',
|
1469
|
+
width: '60%',
|
1470
|
+
height: '40%',
|
1471
|
+
top: '30%',
|
1472
|
+
left: '20%',
|
1473
|
+
backgroundColor: particle.color,
|
1474
|
+
borderRadius: '50% 40% 40% 50%',
|
1475
|
+
boxShadow: `0 2px 10px rgba(0, 0, 0, 0.3)`,
|
1476
|
+
} }),
|
1477
|
+
React.createElement("div", { style: {
|
1478
|
+
position: 'absolute',
|
1479
|
+
width: '35%',
|
1480
|
+
height: '35%',
|
1481
|
+
top: '25%',
|
1482
|
+
right: '15%',
|
1483
|
+
backgroundColor: particle.color,
|
1484
|
+
borderRadius: '40% 50% 50% 40%',
|
1485
|
+
transform: 'rotate(-10deg)',
|
1486
|
+
} },
|
1487
|
+
React.createElement("div", { style: {
|
1488
|
+
position: 'absolute',
|
1489
|
+
width: '20%',
|
1490
|
+
height: '20%',
|
1491
|
+
top: '30%',
|
1492
|
+
right: '25%',
|
1493
|
+
backgroundColor: '#FFD700',
|
1494
|
+
borderRadius: '50%',
|
1495
|
+
boxShadow: '0 0 4px #FFD700',
|
1496
|
+
} })),
|
1497
|
+
React.createElement("div", { style: {
|
1498
|
+
position: 'absolute',
|
1499
|
+
width: '40%',
|
1500
|
+
height: '50%',
|
1501
|
+
top: '15%',
|
1502
|
+
left: '30%',
|
1503
|
+
backgroundColor: `${particle.color}CC`,
|
1504
|
+
clipPath: 'polygon(0% 100%, 50% 0%, 100% 30%, 90% 60%, 100% 90%, 50% 100%)',
|
1505
|
+
transform: `rotateX(${wingFlap}deg)`,
|
1506
|
+
transformOrigin: 'bottom center',
|
1507
|
+
} }),
|
1508
|
+
React.createElement("div", { style: {
|
1509
|
+
position: 'absolute',
|
1510
|
+
width: '40%',
|
1511
|
+
height: '50%',
|
1512
|
+
top: '35%',
|
1513
|
+
left: '30%',
|
1514
|
+
backgroundColor: `${particle.color}AA`,
|
1515
|
+
clipPath: 'polygon(0% 0%, 50% 0%, 100% 30%, 90% 60%, 100% 90%, 50% 100%)',
|
1516
|
+
transform: `rotateX(${-wingFlap}deg)`,
|
1517
|
+
transformOrigin: 'top center',
|
1518
|
+
} }),
|
1519
|
+
React.createElement("div", { style: {
|
1520
|
+
position: 'absolute',
|
1521
|
+
width: '40%',
|
1522
|
+
height: '15%',
|
1523
|
+
top: '35%',
|
1524
|
+
left: '5%',
|
1525
|
+
backgroundColor: particle.color,
|
1526
|
+
clipPath: 'polygon(0% 50%, 70% 0%, 100% 20%, 100% 80%, 70% 100%, 0% 50%)',
|
1527
|
+
} }),
|
1528
|
+
React.createElement("div", { style: {
|
1529
|
+
position: 'absolute',
|
1530
|
+
width: '30%',
|
1531
|
+
height: '20%',
|
1532
|
+
top: '35%',
|
1533
|
+
right: '5%',
|
1534
|
+
background: `radial-gradient(ellipse, #FFD700 0%, #FF4500 50%, transparent 100%)`,
|
1535
|
+
transform: `scale(${0.8 + firePulse * 0.4})`,
|
1536
|
+
opacity: 0.8 + firePulse * 0.2,
|
1537
|
+
filter: 'blur(1px)',
|
1538
|
+
} }),
|
1539
|
+
React.createElement("div", { style: {
|
1540
|
+
position: 'absolute',
|
1541
|
+
width: '25%',
|
1542
|
+
height: '15%',
|
1543
|
+
top: '37%',
|
1544
|
+
right: '0%',
|
1545
|
+
background: `radial-gradient(ellipse, #FFA500 0%, #FF6347 50%, transparent 100%)`,
|
1546
|
+
transform: `scale(${0.6 + firePulse * 0.6})`,
|
1547
|
+
opacity: 0.6 + firePulse * 0.4,
|
1548
|
+
filter: 'blur(2px)',
|
1549
|
+
} })));
|
1550
|
+
};
|
1551
|
+
|
1552
|
+
const defaultColors$a = ['#9C27B0', '#673AB7', '#3F51B5', '#00BCD4', '#4CAF50', '#FFEB3B', '#FF9800'];
|
1553
|
+
// Ancient rune symbols
|
1554
|
+
const runeSymbols = [
|
1555
|
+
'ᚠ', 'ᚢ', 'ᚦ', 'ᚨ', 'ᚱ', 'ᚲ', 'ᚷ', 'ᚹ', 'ᚺ', 'ᚾ', 'ᛁ', 'ᛃ', 'ᛇ', 'ᛈ', 'ᛉ', 'ᛋ', 'ᛏ', 'ᛒ', 'ᛖ', 'ᛗ', 'ᛚ', 'ᛜ', 'ᛞ', 'ᛟ'
|
1556
|
+
];
|
1557
|
+
const createRuneParticles = (origin, config) => {
|
1558
|
+
const { particleCount = 12, startVelocity = 6, colors = defaultColors$a, elementSize = 35 } = config;
|
1559
|
+
const particles = [];
|
1560
|
+
for (let i = 0; i < particleCount; i++) {
|
1561
|
+
// Runes float upward in a mystical pattern
|
1562
|
+
const angle = randomInRange(250, 290); // Mostly upward
|
1563
|
+
const velocity = randomInRange(startVelocity * 0.3, startVelocity * 0.7);
|
1564
|
+
const color = getRandomColor(colors);
|
1565
|
+
// Create circular spawn pattern
|
1566
|
+
const spawnAngle = (i / particleCount) * 360;
|
1567
|
+
const spawnRadius = randomInRange(20, 60);
|
1568
|
+
const runeIndex = Math.floor(Math.random() * runeSymbols.length);
|
1569
|
+
particles.push({
|
1570
|
+
id: generateId(),
|
1571
|
+
x: origin.x + Math.cos(degreesToRadians(spawnAngle)) * spawnRadius,
|
1572
|
+
y: origin.y + Math.sin(degreesToRadians(spawnAngle)) * spawnRadius,
|
1573
|
+
vx: Math.cos(degreesToRadians(angle)) * velocity + randomInRange(-1, 1),
|
1574
|
+
vy: Math.sin(degreesToRadians(angle)) * velocity,
|
1575
|
+
life: config.lifetime || 160,
|
1576
|
+
opacity: 0,
|
1577
|
+
size: randomInRange(elementSize * 0.8, elementSize * 1.2),
|
1578
|
+
// Store runeIndex in lower bits of rotation, keep rotation angle in upper bits
|
1579
|
+
rotation: runeIndex + (Math.floor(randomInRange(0, 360)) * 100),
|
1580
|
+
color,
|
1581
|
+
});
|
1582
|
+
}
|
1583
|
+
return particles;
|
1584
|
+
};
|
1585
|
+
const renderRuneParticle = (particle) => {
|
1586
|
+
// Extract rune index and rotation from encoded value
|
1587
|
+
const runeIndex = particle.rotation % 100;
|
1588
|
+
const rotationAngle = Math.floor(particle.rotation / 100);
|
1589
|
+
const runeSymbol = runeSymbols[runeIndex] || runeSymbols[0];
|
1590
|
+
// Calculate pulsing glow effect
|
1591
|
+
const glowIntensity = (Math.sin(Date.now() * 0.003 + particle.x * 0.01) + 1) / 2;
|
1592
|
+
// Fade in and out based on life
|
1593
|
+
const fadeProgress = particle.life > 120 ? (160 - particle.life) / 40 : particle.life < 40 ? particle.life / 40 : 1;
|
1594
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1595
|
+
width: `${particle.size}px`,
|
1596
|
+
height: `${particle.size}px`,
|
1597
|
+
position: 'relative',
|
1598
|
+
transform: `rotate(${rotationAngle}deg)`,
|
1599
|
+
opacity: fadeProgress,
|
1600
|
+
} },
|
1601
|
+
React.createElement("div", { style: {
|
1602
|
+
position: 'absolute',
|
1603
|
+
width: '100%',
|
1604
|
+
height: '100%',
|
1605
|
+
borderRadius: '50%',
|
1606
|
+
background: `radial-gradient(circle, ${particle.color}44 0%, transparent 70%)`,
|
1607
|
+
transform: `scale(${1.5 + glowIntensity * 0.5})`,
|
1608
|
+
filter: 'blur(4px)',
|
1609
|
+
} }),
|
1610
|
+
React.createElement("div", { style: {
|
1611
|
+
position: 'absolute',
|
1612
|
+
width: '100%',
|
1613
|
+
height: '100%',
|
1614
|
+
borderRadius: '50%',
|
1615
|
+
background: `radial-gradient(circle, ${particle.color}88 0%, ${particle.color}44 50%, transparent 100%)`,
|
1616
|
+
transform: `scale(${1.2 + glowIntensity * 0.3})`,
|
1617
|
+
} }),
|
1618
|
+
React.createElement("div", { style: {
|
1619
|
+
position: 'absolute',
|
1620
|
+
width: '100%',
|
1621
|
+
height: '100%',
|
1622
|
+
display: 'flex',
|
1623
|
+
alignItems: 'center',
|
1624
|
+
justifyContent: 'center',
|
1625
|
+
fontSize: `${particle.size * 0.7}px`,
|
1626
|
+
fontWeight: 'bold',
|
1627
|
+
color: '#FFFFFF',
|
1628
|
+
textShadow: `
|
1629
|
+
0 0 10px ${particle.color},
|
1630
|
+
0 0 20px ${particle.color},
|
1631
|
+
0 0 30px ${particle.color},
|
1632
|
+
0 0 40px ${particle.color}
|
1633
|
+
`,
|
1634
|
+
filter: `brightness(${1.5 + glowIntensity * 0.5})`,
|
1635
|
+
} }, runeSymbol),
|
1636
|
+
[0, 72, 144, 216, 288].map((angle, index) => (React.createElement("div", { key: index, style: {
|
1637
|
+
position: 'absolute',
|
1638
|
+
width: '4px',
|
1639
|
+
height: '4px',
|
1640
|
+
backgroundColor: '#FFFFFF',
|
1641
|
+
borderRadius: '50%',
|
1642
|
+
top: '50%',
|
1643
|
+
left: '50%',
|
1644
|
+
transform: `
|
1645
|
+
translate(-50%, -50%)
|
1646
|
+
rotate(${angle + rotationAngle}deg)
|
1647
|
+
translateY(-${particle.size * 0.6}px)
|
1648
|
+
scale(${0.5 + glowIntensity})
|
1649
|
+
`,
|
1650
|
+
boxShadow: '0 0 6px #FFFFFF',
|
1651
|
+
opacity: glowIntensity,
|
1652
|
+
} })))));
|
1653
|
+
};
|
1654
|
+
|
1655
|
+
const defaultColors$9 = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#F7DC6F', '#BB8FCE'];
|
1656
|
+
const createButterflyParticles = (origin, config) => {
|
1657
|
+
const { particleCount = 6, startVelocity = 3, colors = defaultColors$9, elementSize = 40 } = config;
|
1658
|
+
const particles = [];
|
1659
|
+
for (let i = 0; i < particleCount; i++) {
|
1660
|
+
const angle = randomInRange(0, 360);
|
1661
|
+
const velocity = randomInRange(startVelocity * 0.5, startVelocity);
|
1662
|
+
particles.push({
|
1663
|
+
id: generateId(),
|
1664
|
+
x: origin.x + randomInRange(-50, 50),
|
1665
|
+
y: origin.y + randomInRange(-30, 30),
|
1666
|
+
vx: Math.cos(angle * Math.PI / 180) * velocity,
|
1667
|
+
vy: -Math.abs(Math.sin(angle * Math.PI / 180) * velocity * 0.5), // Float upward
|
1668
|
+
life: config.lifetime || 200,
|
1669
|
+
opacity: 1,
|
1670
|
+
size: randomInRange(elementSize * 0.8, elementSize * 1.2),
|
1671
|
+
// Encode wing phase (0-360), wobble phase (0-360), and rotation speed (-10 to 10)
|
1672
|
+
rotation: Math.floor(randomInRange(0, 360)) + (Math.floor(randomInRange(0, 360)) * 1000) + ((Math.floor(randomInRange(-10, 10)) + 10) * 1000000),
|
1673
|
+
color: getRandomColor(colors),
|
1674
|
+
});
|
1675
|
+
}
|
1676
|
+
return particles;
|
1677
|
+
};
|
1678
|
+
const renderButterflyParticle = (particle) => {
|
1679
|
+
// Extract encoded values
|
1680
|
+
const wingPhase = (particle.rotation % 1000);
|
1681
|
+
const wobblePhase = Math.floor((particle.rotation % 1000000) / 1000);
|
1682
|
+
const rotationSpeed = (Math.floor(particle.rotation / 1000000) - 10) / 10;
|
1683
|
+
// Calculate wing flapping and wobble
|
1684
|
+
const wingAngle = Math.sin((Date.now() * 0.01 + wingPhase) * Math.PI / 180) * 30;
|
1685
|
+
const wobbleX = Math.sin((Date.now() * 0.003 + wobblePhase) * Math.PI / 180) * 10;
|
1686
|
+
const rotation = (Date.now() * rotationSpeed * 0.01) % 360;
|
1687
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1688
|
+
width: `${particle.size}px`,
|
1689
|
+
height: `${particle.size}px`,
|
1690
|
+
position: 'relative',
|
1691
|
+
transform: `translateX(${wobbleX}px) rotate(${rotation}deg)`,
|
1692
|
+
} },
|
1693
|
+
React.createElement("svg", { width: particle.size, height: particle.size, viewBox: "-25 -25 50 50", style: {
|
1694
|
+
position: 'absolute',
|
1695
|
+
top: 0,
|
1696
|
+
left: 0,
|
1697
|
+
} },
|
1698
|
+
React.createElement("ellipse", { cx: "-8", cy: "0", rx: "12", ry: "18", fill: particle.color, opacity: "0.8", transform: `rotate(${-wingAngle} 0 0)` }),
|
1699
|
+
React.createElement("ellipse", { cx: "-6", cy: "-10", rx: "8", ry: "12", fill: particle.color, opacity: "0.6", transform: `rotate(${-wingAngle - 15} 0 0)` }),
|
1700
|
+
React.createElement("ellipse", { cx: "8", cy: "0", rx: "12", ry: "18", fill: particle.color, opacity: "0.8", transform: `rotate(${wingAngle} 0 0)` }),
|
1701
|
+
React.createElement("ellipse", { cx: "6", cy: "-10", rx: "8", ry: "12", fill: particle.color, opacity: "0.6", transform: `rotate(${wingAngle + 15} 0 0)` }),
|
1702
|
+
React.createElement("ellipse", { cx: "0", cy: "0", rx: "3", ry: "15", fill: "#333" }),
|
1703
|
+
React.createElement("line", { x1: "0", y1: "-12", x2: "-3", y2: "-18", stroke: "#333", strokeWidth: "1" }),
|
1704
|
+
React.createElement("line", { x1: "0", y1: "-12", x2: "3", y2: "-18", stroke: "#333", strokeWidth: "1" }),
|
1705
|
+
React.createElement("circle", { cx: "-8", cy: "0", r: "3", fill: "white", opacity: "0.4" }),
|
1706
|
+
React.createElement("circle", { cx: "8", cy: "0", r: "3", fill: "white", opacity: "0.4" }),
|
1707
|
+
React.createElement("circle", { cx: "-6", cy: "-8", r: "2", fill: "black", opacity: "0.3" }),
|
1708
|
+
React.createElement("circle", { cx: "6", cy: "-8", r: "2", fill: "black", opacity: "0.3" }))));
|
1709
|
+
};
|
1710
|
+
|
1711
|
+
const defaultColors$8 = ['#D2691E', '#CD853F', '#8B4513', '#A0522D', '#FF8C00', '#FF6347'];
|
1712
|
+
const createLeafParticles = (origin, config) => {
|
1713
|
+
const { particleCount = 10, colors = defaultColors$8, elementSize = 25 } = config;
|
1714
|
+
const particles = [];
|
1715
|
+
for (let i = 0; i < particleCount; i++) {
|
1716
|
+
particles.push({
|
1717
|
+
id: generateId(),
|
1718
|
+
x: origin.x + randomInRange(-100, 100),
|
1719
|
+
y: origin.y + randomInRange(-50, 0),
|
1720
|
+
vx: randomInRange(-1, 1),
|
1721
|
+
vy: randomInRange(0.5, 2),
|
1722
|
+
life: config.lifetime || 300,
|
1723
|
+
opacity: 1,
|
1724
|
+
size: randomInRange(elementSize * 0.6, elementSize),
|
1725
|
+
// Encode tumble phase (0-360), sway phase (0-360), and sway amount (20-40) + rotation speed (-3 to 3)
|
1726
|
+
rotation: Math.floor(randomInRange(0, 360)) +
|
1727
|
+
(Math.floor(randomInRange(0, 360)) * 1000) +
|
1728
|
+
(Math.floor(randomInRange(20, 40)) * 1000000) +
|
1729
|
+
((Math.floor(randomInRange(-3, 3)) + 3) * 100000000),
|
1730
|
+
color: getRandomColor(colors),
|
1731
|
+
});
|
1732
|
+
}
|
1733
|
+
return particles;
|
1734
|
+
};
|
1735
|
+
const renderLeafParticle = (particle) => {
|
1736
|
+
// Extract encoded values
|
1737
|
+
const tumblePhase = particle.rotation % 1000;
|
1738
|
+
const swayPhase = Math.floor((particle.rotation % 1000000) / 1000);
|
1739
|
+
const swayAmount = Math.floor((particle.rotation % 100000000) / 1000000);
|
1740
|
+
const rotationSpeed = (Math.floor(particle.rotation / 100000000) - 3);
|
1741
|
+
// Calculate tumbling and swaying
|
1742
|
+
const tumble = Math.sin((Date.now() * 0.002 + tumblePhase) * Math.PI / 180) * 30;
|
1743
|
+
const swayX = Math.sin((Date.now() * 0.001 + swayPhase) * Math.PI / 180) * swayAmount;
|
1744
|
+
const rotation = (Date.now() * rotationSpeed * 0.01 + tumble) % 360;
|
1745
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1746
|
+
width: `${particle.size}px`,
|
1747
|
+
height: `${particle.size}px`,
|
1748
|
+
position: 'relative',
|
1749
|
+
transform: `translateX(${swayX}px) rotate(${rotation}deg)`,
|
1750
|
+
} },
|
1751
|
+
React.createElement("svg", { width: particle.size, height: particle.size, viewBox: `-${particle.size / 2} -${particle.size / 2} ${particle.size} ${particle.size}`, style: {
|
1752
|
+
position: 'absolute',
|
1753
|
+
top: 0,
|
1754
|
+
left: 0,
|
1755
|
+
} },
|
1756
|
+
React.createElement("path", { d: `
|
1757
|
+
M 0,-${particle.size / 2}
|
1758
|
+
C -${particle.size / 3},-${particle.size / 3} -${particle.size / 3},${particle.size / 3} 0,${particle.size / 2}
|
1759
|
+
C ${particle.size / 3},${particle.size / 3} ${particle.size / 3},-${particle.size / 3} 0,-${particle.size / 2}
|
1760
|
+
`, fill: particle.color, opacity: "0.9" }),
|
1761
|
+
React.createElement("line", { x1: "0", y1: -particle.size / 2, x2: "0", y2: particle.size / 2, stroke: "#8B4513", strokeWidth: "1", opacity: "0.5" }),
|
1762
|
+
React.createElement("line", { x1: "0", y1: -particle.size / 4, x2: -particle.size / 4, y2: -particle.size / 8, stroke: "#8B4513", strokeWidth: "0.5", opacity: "0.5" }),
|
1763
|
+
React.createElement("line", { x1: "0", y1: -particle.size / 4, x2: particle.size / 4, y2: -particle.size / 8, stroke: "#8B4513", strokeWidth: "0.5", opacity: "0.5" }),
|
1764
|
+
React.createElement("line", { x1: "0", y1: particle.size / 4, x2: -particle.size / 4, y2: particle.size / 8, stroke: "#8B4513", strokeWidth: "0.5", opacity: "0.5" }),
|
1765
|
+
React.createElement("line", { x1: "0", y1: particle.size / 4, x2: particle.size / 4, y2: particle.size / 8, stroke: "#8B4513", strokeWidth: "0.5", opacity: "0.5" }))));
|
1766
|
+
};
|
1767
|
+
|
1768
|
+
const defaultColors$7 = ['#4A90E2', '#5BA0F2', '#6BB0FF', '#3A80D2'];
|
1769
|
+
const createRainParticles = (origin, config) => {
|
1770
|
+
const { particleCount = 50, colors = defaultColors$7, elementSize = 300 } = config;
|
1771
|
+
const particles = [];
|
1772
|
+
for (let i = 0; i < particleCount; i++) {
|
1773
|
+
particles.push({
|
1774
|
+
id: generateId(),
|
1775
|
+
x: randomInRange(origin.x - elementSize / 2, origin.x + elementSize / 2),
|
1776
|
+
y: origin.y - randomInRange(0, elementSize),
|
1777
|
+
vx: randomInRange(-0.5, 0.5),
|
1778
|
+
vy: randomInRange(8, 12),
|
1779
|
+
life: config.lifetime || 150,
|
1780
|
+
opacity: randomInRange(0.3, 0.7),
|
1781
|
+
size: randomInRange(2, 4),
|
1782
|
+
// Encode: length (15-25) + splashing state (0 or 1) * 100 + splash frame (0-15) * 1000
|
1783
|
+
rotation: Math.floor(randomInRange(15, 25)),
|
1784
|
+
color: getRandomColor(colors),
|
1785
|
+
});
|
1786
|
+
}
|
1787
|
+
return particles;
|
1788
|
+
};
|
1789
|
+
const renderRainParticle = (particle) => {
|
1790
|
+
// Extract encoded values
|
1791
|
+
const length = particle.rotation % 100;
|
1792
|
+
const isSplashing = Math.floor((particle.rotation % 1000) / 100) === 1;
|
1793
|
+
const splashFrame = Math.floor(particle.rotation / 1000);
|
1794
|
+
// Render splash effect
|
1795
|
+
if (isSplashing && splashFrame < 15) {
|
1796
|
+
const splashRadius = splashFrame * 2;
|
1797
|
+
const splashOpacity = Math.max(0, 1 - splashFrame / 15) * 0.5;
|
1798
|
+
return (React.createElement("div", { key: particle.id, style: { position: 'relative' } },
|
1799
|
+
React.createElement("svg", { width: splashRadius * 4, height: splashRadius * 2, style: {
|
1800
|
+
position: 'absolute',
|
1801
|
+
left: -splashRadius * 2,
|
1802
|
+
top: -splashRadius,
|
1803
|
+
} },
|
1804
|
+
React.createElement("ellipse", { cx: splashRadius * 2, cy: splashRadius, rx: splashRadius, ry: splashRadius / 3, fill: "none", stroke: particle.color, strokeWidth: "1", opacity: splashOpacity }),
|
1805
|
+
[0, 1, 2, 3].map((i) => {
|
1806
|
+
const angle = (i * 90 + 45) * Math.PI / 180;
|
1807
|
+
const distance = splashFrame * 1.5;
|
1808
|
+
const dropX = splashRadius * 2 + Math.cos(angle) * distance;
|
1809
|
+
const dropY = splashRadius - Math.sin(angle) * distance + splashFrame * 0.5;
|
1810
|
+
return (React.createElement("circle", { key: i, cx: dropX, cy: dropY, r: "1.5", fill: particle.color, opacity: splashOpacity }));
|
1811
|
+
}))));
|
1812
|
+
}
|
1813
|
+
// Render falling raindrop
|
1814
|
+
return (React.createElement("div", { key: particle.id, style: { position: 'relative' } },
|
1815
|
+
React.createElement("svg", { width: particle.size * 2, height: length + particle.size * 3, style: {
|
1816
|
+
position: 'absolute',
|
1817
|
+
left: -particle.size,
|
1818
|
+
top: -length,
|
1819
|
+
} },
|
1820
|
+
React.createElement("line", { x1: particle.size, y1: 0, x2: particle.size, y2: length, stroke: particle.color, strokeWidth: particle.size, strokeLinecap: "round", opacity: particle.opacity * 0.3 }),
|
1821
|
+
React.createElement("ellipse", { cx: particle.size, cy: length + particle.size * 1.5, rx: particle.size, ry: particle.size * 1.5, fill: particle.color, opacity: particle.opacity }))));
|
1822
|
+
};
|
1823
|
+
|
1824
|
+
const defaultColors$6 = ['#FFFFFF', '#F5F5F5', '#FAFAFA'];
|
1825
|
+
const createDandelionParticles = (origin, config) => {
|
1826
|
+
const { particleCount = 15, colors = defaultColors$6, elementSize = 15 } = config;
|
1827
|
+
const particles = [];
|
1828
|
+
for (let i = 0; i < particleCount; i++) {
|
1829
|
+
particles.push({
|
1830
|
+
id: generateId(),
|
1831
|
+
x: origin.x + randomInRange(-20, 20),
|
1832
|
+
y: origin.y + randomInRange(-20, 20),
|
1833
|
+
vx: randomInRange(-2, 2),
|
1834
|
+
vy: randomInRange(-1, -0.3),
|
1835
|
+
life: config.lifetime || 200,
|
1836
|
+
opacity: 1,
|
1837
|
+
size: randomInRange(elementSize * 0.8, elementSize * 1.2),
|
1838
|
+
// Encode: rotation angle + float phase * 1000 + drift phase * 1000000
|
1839
|
+
rotation: Math.floor(randomInRange(0, 360)) +
|
1840
|
+
(Math.floor(randomInRange(0, 360)) * 1000) +
|
1841
|
+
(Math.floor(randomInRange(0, 360)) * 1000000),
|
1842
|
+
color: getRandomColor(colors),
|
1843
|
+
});
|
1844
|
+
}
|
1845
|
+
return particles;
|
1846
|
+
};
|
1847
|
+
const renderDandelionParticle = (particle) => {
|
1848
|
+
// Extract encoded values
|
1849
|
+
const rotationAngle = particle.rotation % 1000;
|
1850
|
+
const floatPhase = Math.floor((particle.rotation % 1000000) / 1000);
|
1851
|
+
const driftPhase = Math.floor(particle.rotation / 1000000);
|
1852
|
+
// Calculate floating effects
|
1853
|
+
const floatY = Math.sin((Date.now() * 0.002 + floatPhase) * Math.PI / 180) * 5;
|
1854
|
+
const driftX = Math.sin((Date.now() * 0.001 + driftPhase) * Math.PI / 180) * 3;
|
1855
|
+
const rotation = (Date.now() * 0.01 + rotationAngle) % 360;
|
1856
|
+
const seedCount = 7;
|
1857
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1858
|
+
width: `${particle.size * 2}px`,
|
1859
|
+
height: `${particle.size * 2}px`,
|
1860
|
+
position: 'relative',
|
1861
|
+
transform: `translate(${driftX}px, ${floatY}px) rotate(${rotation}deg)`,
|
1862
|
+
opacity: particle.opacity,
|
1863
|
+
} },
|
1864
|
+
React.createElement("svg", { width: particle.size * 2, height: particle.size * 2, viewBox: `-${particle.size} -${particle.size} ${particle.size * 2} ${particle.size * 2}`, style: {
|
1865
|
+
position: 'absolute',
|
1866
|
+
top: 0,
|
1867
|
+
left: 0,
|
1868
|
+
} },
|
1869
|
+
React.createElement("circle", { cx: "0", cy: "0", r: "2", fill: "#F5F5DC" }),
|
1870
|
+
Array.from({ length: seedCount }).map((_, i) => {
|
1871
|
+
const angle = (i * 360 / seedCount) * Math.PI / 180;
|
1872
|
+
const endX = Math.cos(angle) * particle.size;
|
1873
|
+
const endY = Math.sin(angle) * particle.size;
|
1874
|
+
const midX = Math.cos(angle) * particle.size * 0.7;
|
1875
|
+
const midY = Math.sin(angle) * particle.size * 0.7;
|
1876
|
+
return (React.createElement("g", { key: i },
|
1877
|
+
React.createElement("line", { x1: "0", y1: "0", x2: endX, y2: endY, stroke: "#E5E5E5", strokeWidth: "0.5", opacity: "0.8" }),
|
1878
|
+
React.createElement("circle", { cx: endX, cy: endY, r: "3", fill: particle.color, opacity: "0.6" }),
|
1879
|
+
React.createElement("circle", { cx: midX, cy: midY, r: "2", fill: particle.color, opacity: "0.4" }),
|
1880
|
+
[0, 1, 2].map((j) => {
|
1881
|
+
const filamentAngle = angle + (j - 1) * 0.1;
|
1882
|
+
const filamentX = endX + Math.cos(filamentAngle) * 2;
|
1883
|
+
const filamentY = endY + Math.sin(filamentAngle) * 2;
|
1884
|
+
return (React.createElement("line", { key: j, x1: endX, y1: endY, x2: filamentX, y2: filamentY, stroke: "#E5E5E5", strokeWidth: "0.3", opacity: "0.6" }));
|
1885
|
+
})));
|
1886
|
+
}))));
|
1887
|
+
};
|
1888
|
+
|
1889
|
+
const defaultColors$5 = ['#FFD700', '#FFA500'];
|
1890
|
+
const createBeeParticles = (origin, config) => {
|
1891
|
+
const { particleCount = 5, colors = defaultColors$5, elementSize = 18 } = config;
|
1892
|
+
const particles = [];
|
1893
|
+
for (let i = 0; i < particleCount; i++) {
|
1894
|
+
particles.push({
|
1895
|
+
id: generateId(),
|
1896
|
+
x: origin.x + randomInRange(-50, 50),
|
1897
|
+
y: origin.y + randomInRange(-50, 50),
|
1898
|
+
vx: randomInRange(2, 4),
|
1899
|
+
vy: randomInRange(-1, 1),
|
1900
|
+
life: config.lifetime || 300,
|
1901
|
+
opacity: 1,
|
1902
|
+
size: randomInRange(elementSize * 0.8, elementSize * 1.1),
|
1903
|
+
// Encode: zigzag phase (0-360) + wing phase (0-360) * 1000 + buzz phase (0-360) * 1000000
|
1904
|
+
rotation: Math.floor(randomInRange(0, 360)) +
|
1905
|
+
(Math.floor(randomInRange(0, 360)) * 1000) +
|
1906
|
+
(Math.floor(randomInRange(0, 360)) * 1000000),
|
1907
|
+
color: getRandomColor(colors),
|
1908
|
+
});
|
1909
|
+
}
|
1910
|
+
return particles;
|
1911
|
+
};
|
1912
|
+
const renderBeeParticle = (particle) => {
|
1913
|
+
// Extract encoded values
|
1914
|
+
const zigzagPhase = particle.rotation % 1000;
|
1915
|
+
const wingPhase = Math.floor((particle.rotation % 1000000) / 1000);
|
1916
|
+
const buzzPhase = Math.floor(particle.rotation / 1000000);
|
1917
|
+
// Calculate animations
|
1918
|
+
const zigzagY = Math.sin((Date.now() * 0.005 + zigzagPhase) * Math.PI / 180) * 15;
|
1919
|
+
const wingAngle = Math.sin((Date.now() * 0.02 + wingPhase) * Math.PI / 180) * 20;
|
1920
|
+
const buzzOffset = Math.sin((Date.now() * 0.015 + buzzPhase) * Math.PI / 180) * 2;
|
1921
|
+
// Calculate rotation based on movement direction
|
1922
|
+
const movementAngle = Math.atan2(particle.vy, particle.vx) * 180 / Math.PI;
|
1923
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1924
|
+
width: `${particle.size * 2}px`,
|
1925
|
+
height: `${particle.size * 2}px`,
|
1926
|
+
position: 'relative',
|
1927
|
+
transform: `translate(${buzzOffset}px, ${zigzagY}px) rotate(${movementAngle}deg)`,
|
1928
|
+
} },
|
1929
|
+
React.createElement("svg", { width: particle.size * 2, height: particle.size * 2, viewBox: "-15 -10 30 20", style: {
|
1930
|
+
position: 'absolute',
|
1931
|
+
top: 0,
|
1932
|
+
left: 0,
|
1933
|
+
} },
|
1934
|
+
React.createElement("ellipse", { cx: "-2", cy: "-3", rx: "8", ry: "4", fill: "#E5E5E5", opacity: "0.7", transform: `rotate(${-wingAngle - 20} -2 -3)` }),
|
1935
|
+
React.createElement("ellipse", { cx: "-2", cy: "3", rx: "8", ry: "4", fill: "#E5E5E5", opacity: "0.7", transform: `rotate(${wingAngle + 20} -2 3)` }),
|
1936
|
+
React.createElement("ellipse", { cx: "0", cy: "0", rx: "8", ry: "6", fill: particle.color }),
|
1937
|
+
React.createElement("ellipse", { cx: "-6", cy: "0", rx: "6", ry: "5", fill: "#333" }),
|
1938
|
+
React.createElement("rect", { x: "-3", y: "-6", width: "2", height: "12", fill: "#333" }),
|
1939
|
+
React.createElement("rect", { x: "1", y: "-6", width: "2", height: "12", fill: "#333" }),
|
1940
|
+
React.createElement("rect", { x: "5", y: "-5", width: "2", height: "10", fill: "#333" }),
|
1941
|
+
React.createElement("circle", { cx: "8", cy: "0", r: "4", fill: "#333" }),
|
1942
|
+
React.createElement("circle", { cx: "9", cy: "-1.5", r: "1", fill: "#FFF" }),
|
1943
|
+
React.createElement("circle", { cx: "9", cy: "1.5", r: "1", fill: "#FFF" }),
|
1944
|
+
React.createElement("line", { x1: "10", y1: "-2", x2: "12", y2: "-4", stroke: "#333", strokeWidth: "0.5" }),
|
1945
|
+
React.createElement("line", { x1: "10", y1: "2", x2: "12", y2: "4", stroke: "#333", strokeWidth: "0.5" }),
|
1946
|
+
React.createElement("polygon", { points: "-10,0 -12,1 -12,-1", fill: "#333" }))));
|
1947
|
+
};
|
1948
|
+
|
1949
|
+
const defaultColors$4 = ['#FFE5B4', '#FFF8DC', '#FFFACD', '#FFF5EE'];
|
1950
|
+
const createPopcornParticles = (origin, config) => {
|
1951
|
+
const { particleCount = 20, startVelocity = 25, colors = defaultColors$4, elementSize = 20 } = config;
|
1952
|
+
const particles = [];
|
1953
|
+
for (let i = 0; i < particleCount; i++) {
|
1954
|
+
const angle = randomInRange(0, 360);
|
1955
|
+
const velocity = randomInRange(startVelocity * 0.5, startVelocity);
|
1956
|
+
particles.push({
|
1957
|
+
id: generateId(),
|
1958
|
+
x: origin.x,
|
1959
|
+
y: origin.y,
|
1960
|
+
vx: Math.cos(degreesToRadians(angle)) * velocity,
|
1961
|
+
vy: Math.sin(degreesToRadians(angle)) * velocity - 10, // Initial upward boost
|
1962
|
+
life: config.lifetime || 150,
|
1963
|
+
opacity: 1,
|
1964
|
+
size: randomInRange(elementSize * 0.8, elementSize * 1.2),
|
1965
|
+
rotation: randomInRange(0, 360),
|
1966
|
+
color: getRandomColor(colors),
|
1967
|
+
});
|
1968
|
+
}
|
1969
|
+
return particles;
|
1970
|
+
};
|
1971
|
+
const renderPopcornParticle = (particle) => {
|
1972
|
+
// Add some rotation animation
|
1973
|
+
const rotation = particle.rotation + (150 - particle.life) * 3;
|
1974
|
+
// Add bounce effect
|
1975
|
+
const bounceProgress = (150 - particle.life) / 150;
|
1976
|
+
const scale = 0.5 + Math.sin(bounceProgress * Math.PI) * 0.5;
|
1977
|
+
return (React.createElement("div", { key: particle.id, style: {
|
1978
|
+
fontSize: `${particle.size}px`,
|
1979
|
+
transform: `rotate(${rotation}deg) scale(${scale})`,
|
1980
|
+
opacity: particle.opacity,
|
1981
|
+
userSelect: 'none',
|
1982
|
+
} }, "\uD83C\uDF7F"));
|
1983
|
+
};
|
1984
|
+
|
1985
|
+
const defaultColors$3 = ['#F0E68C', '#FFD700', '#FFF8DC', '#FFFACD', '#F5DEB3'];
|
1986
|
+
const createChampagneParticles = (origin, config) => {
|
1987
|
+
const { particleCount = 40, startVelocity = 30, colors = defaultColors$3, elementSize = 12 } = config;
|
1988
|
+
const particles = [];
|
1989
|
+
for (let i = 0; i < particleCount; i++) {
|
1990
|
+
const isBubble = i < particleCount * 0.7;
|
1991
|
+
const angle = isBubble
|
1992
|
+
? randomInRange(60, 120) // Mostly upward for bubbles
|
1993
|
+
: randomInRange(0, 360); // Any direction for cork
|
1994
|
+
const velocity = randomInRange(startVelocity * 0.5, startVelocity);
|
1995
|
+
particles.push({
|
1996
|
+
id: generateId(),
|
1997
|
+
x: origin.x,
|
1998
|
+
y: origin.y,
|
1999
|
+
vx: Math.cos(degreesToRadians(angle)) * velocity,
|
2000
|
+
vy: Math.sin(degreesToRadians(angle)) * velocity * (isBubble ? -1 : 1),
|
2001
|
+
life: config.lifetime || 200,
|
2002
|
+
opacity: isBubble ? 0.6 : 1,
|
2003
|
+
size: isBubble ? randomInRange(4, 8) : elementSize,
|
2004
|
+
// Encode: isBubble (0 or 1) + wobble phase * 10
|
2005
|
+
rotation: (isBubble ? 0 : 1) + Math.floor(randomInRange(0, 360)) * 10,
|
2006
|
+
color: getRandomColor(colors),
|
2007
|
+
});
|
2008
|
+
}
|
2009
|
+
return particles;
|
2010
|
+
};
|
2011
|
+
const renderChampagneParticle = (particle) => {
|
2012
|
+
const isBubble = (particle.rotation % 10) === 0;
|
2013
|
+
const wobblePhase = Math.floor(particle.rotation / 10);
|
2014
|
+
if (isBubble) {
|
2015
|
+
// Render bubble
|
2016
|
+
const wobble = Math.sin((Date.now() * 0.003 + wobblePhase) * Math.PI / 180) * 10;
|
2017
|
+
return (React.createElement("div", { key: particle.id, style: {
|
2018
|
+
width: `${particle.size}px`,
|
2019
|
+
height: `${particle.size}px`,
|
2020
|
+
borderRadius: '50%',
|
2021
|
+
backgroundColor: particle.color,
|
2022
|
+
opacity: particle.opacity,
|
2023
|
+
border: `1px solid ${particle.color}`,
|
2024
|
+
transform: `translateX(${wobble}px)`,
|
2025
|
+
boxShadow: `inset -2px -2px 4px rgba(0,0,0,0.1), inset 2px 2px 4px rgba(255,255,255,0.5)`,
|
2026
|
+
} }));
|
2027
|
+
}
|
2028
|
+
// Render cork (champagne bottle)
|
2029
|
+
const rotation = (Date.now() * 0.2 + wobblePhase) % 360;
|
2030
|
+
return (React.createElement("div", { key: particle.id, style: {
|
2031
|
+
fontSize: `${particle.size}px`,
|
2032
|
+
transform: `rotate(${rotation}deg)`,
|
2033
|
+
opacity: particle.opacity,
|
2034
|
+
userSelect: 'none',
|
2035
|
+
} }, "\uD83C\uDF7E"));
|
2036
|
+
};
|
2037
|
+
|
2038
|
+
const defaultColors$2 = ['#FF69B4', '#FF1493', '#FFB6C1', '#FFC0CB', '#FF6347', '#FFA500', '#FFD700', '#98FB98', '#87CEEB', '#DDA0DD'];
|
2039
|
+
const candyEmojis = ['🍬', '🍭', '🍮', '🍯'];
|
2040
|
+
const createCandyParticles = (origin, config) => {
|
2041
|
+
const { particleCount = 20, startVelocity = 20, colors = defaultColors$2, elementSize = 25 } = config;
|
2042
|
+
const particles = [];
|
2043
|
+
for (let i = 0; i < particleCount; i++) {
|
2044
|
+
const angle = randomInRange(-30, 30); // Mostly falling down
|
2045
|
+
const velocity = randomInRange(startVelocity * 0.5, startVelocity);
|
2046
|
+
particles.push({
|
2047
|
+
id: generateId(),
|
2048
|
+
x: origin.x,
|
2049
|
+
y: origin.y - 50, // Start above origin
|
2050
|
+
vx: Math.sin(angle * Math.PI / 180) * velocity * 0.5,
|
2051
|
+
vy: randomInRange(3, 6), // Fall down
|
2052
|
+
life: config.lifetime || 180,
|
2053
|
+
opacity: 1,
|
2054
|
+
size: randomInRange(elementSize * 0.7, elementSize * 1.3),
|
2055
|
+
// Encode candy type (0-3) + initial rotation * 10
|
2056
|
+
rotation: Math.floor(Math.random() * candyEmojis.length) + (Math.floor(randomInRange(0, 360)) * 10),
|
2057
|
+
color: getRandomColor(colors),
|
2058
|
+
});
|
2059
|
+
}
|
2060
|
+
return particles;
|
2061
|
+
};
|
2062
|
+
const renderCandyParticle = (particle) => {
|
2063
|
+
const candyIndex = particle.rotation % 10;
|
2064
|
+
const initialRotation = Math.floor(particle.rotation / 10);
|
2065
|
+
const candy = candyEmojis[candyIndex] || candyEmojis[0];
|
2066
|
+
// Add tumbling rotation
|
2067
|
+
const tumbleSpeed = 5;
|
2068
|
+
const rotation = initialRotation + (180 - particle.life) * tumbleSpeed;
|
2069
|
+
// Add sway effect
|
2070
|
+
const swayAmount = Math.sin((180 - particle.life) * 0.05) * 20;
|
2071
|
+
return (React.createElement("div", { key: particle.id, style: {
|
2072
|
+
fontSize: `${particle.size}px`,
|
2073
|
+
transform: `translateX(${swayAmount}px) rotate(${rotation}deg)`,
|
2074
|
+
opacity: particle.opacity,
|
2075
|
+
userSelect: 'none',
|
2076
|
+
} }, candy));
|
2077
|
+
};
|
2078
|
+
|
2079
|
+
const defaultColors$1 = ['#FFB6C1', '#FF69B4', '#FFD700', '#FF6347', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E2'];
|
2080
|
+
const createDonutParticles = (origin, config) => {
|
2081
|
+
const { particleCount = 15, startVelocity = 25, colors = defaultColors$1, elementSize = 30 } = config;
|
2082
|
+
const particles = [];
|
2083
|
+
for (let i = 0; i < particleCount; i++) {
|
2084
|
+
const angle = randomInRange(0, 360);
|
2085
|
+
const velocity = randomInRange(startVelocity * 0.5, startVelocity);
|
2086
|
+
particles.push({
|
2087
|
+
id: generateId(),
|
2088
|
+
x: origin.x,
|
2089
|
+
y: origin.y,
|
2090
|
+
vx: Math.cos(degreesToRadians(angle)) * velocity,
|
2091
|
+
vy: Math.sin(degreesToRadians(angle)) * velocity - 10, // Initial upward boost
|
2092
|
+
life: config.lifetime || 200,
|
2093
|
+
opacity: 1,
|
2094
|
+
size: randomInRange(elementSize * 0.6, elementSize * 1.4),
|
2095
|
+
rotation: randomInRange(0, 360),
|
2096
|
+
color: getRandomColor(colors),
|
2097
|
+
});
|
2098
|
+
}
|
2099
|
+
return particles;
|
2100
|
+
};
|
2101
|
+
const renderDonutParticle = (particle) => {
|
2102
|
+
// Add spinning animation
|
2103
|
+
const spinSpeed = 8;
|
2104
|
+
const rotation = particle.rotation + (200 - particle.life) * spinSpeed;
|
2105
|
+
// Add bounce effect
|
2106
|
+
const bounceProgress = (200 - particle.life) / 200;
|
2107
|
+
const scale = 0.9 + Math.sin(bounceProgress * Math.PI * 2) * 0.1;
|
2108
|
+
return (React.createElement("div", { key: particle.id, style: {
|
2109
|
+
fontSize: `${particle.size}px`,
|
2110
|
+
transform: `rotate(${rotation}deg) scale(${scale})`,
|
2111
|
+
opacity: particle.opacity,
|
2112
|
+
userSelect: 'none',
|
2113
|
+
position: 'relative',
|
2114
|
+
} },
|
2115
|
+
"\uD83C\uDF69",
|
2116
|
+
[0, 120, 240].map((angle, i) => (React.createElement("div", { key: i, style: {
|
2117
|
+
position: 'absolute',
|
2118
|
+
width: '3px',
|
2119
|
+
height: '8px',
|
2120
|
+
backgroundColor: particle.color,
|
2121
|
+
borderRadius: '40%',
|
2122
|
+
top: '50%',
|
2123
|
+
left: '50%',
|
2124
|
+
transform: `
|
2125
|
+
translate(-50%, -50%)
|
2126
|
+
rotate(${angle + rotation}deg)
|
2127
|
+
translateY(${particle.size * 0.3}px)
|
2128
|
+
scale(${scale})
|
2129
|
+
`,
|
2130
|
+
opacity: particle.opacity * 0.8,
|
2131
|
+
} })))));
|
2132
|
+
};
|
2133
|
+
|
2134
|
+
const defaultColors = ['#FF6347', '#FFD700', '#98D8C8', '#FF8C00', '#DC143C'];
|
2135
|
+
const createPizzaParticles = (origin, config) => {
|
2136
|
+
const { particleCount = 12, startVelocity = 30, colors = defaultColors, elementSize = 35 } = config;
|
2137
|
+
const particles = [];
|
2138
|
+
for (let i = 0; i < particleCount; i++) {
|
2139
|
+
const angle = randomInRange(0, 360);
|
2140
|
+
const velocity = randomInRange(startVelocity * 0.5, startVelocity);
|
2141
|
+
particles.push({
|
2142
|
+
id: generateId(),
|
2143
|
+
x: origin.x,
|
2144
|
+
y: origin.y,
|
2145
|
+
vx: Math.cos(degreesToRadians(angle)) * velocity,
|
2146
|
+
vy: Math.sin(degreesToRadians(angle)) * velocity - 15, // Initial upward boost
|
2147
|
+
life: config.lifetime || 180,
|
2148
|
+
opacity: 1,
|
2149
|
+
size: randomInRange(elementSize * 0.5, elementSize * 1.2),
|
2150
|
+
rotation: randomInRange(0, 360),
|
2151
|
+
color: getRandomColor(colors),
|
2152
|
+
});
|
2153
|
+
}
|
2154
|
+
return particles;
|
2155
|
+
};
|
2156
|
+
const renderPizzaParticle = (particle) => {
|
2157
|
+
// Add spinning and flipping animation
|
2158
|
+
const spinSpeed = 10;
|
2159
|
+
const rotation = particle.rotation + (180 - particle.life) * spinSpeed;
|
2160
|
+
const flipAngle = (180 - particle.life) * 2;
|
2161
|
+
// Add wobble effect
|
2162
|
+
const wobble = Math.sin((180 - particle.life) * 0.1) * 10;
|
2163
|
+
// Scale animation
|
2164
|
+
const progress = (180 - particle.life) / 180;
|
2165
|
+
const scale = 0.8 + Math.sin(progress * Math.PI) * 0.2;
|
2166
|
+
return (React.createElement("div", { key: particle.id, style: {
|
2167
|
+
fontSize: `${particle.size}px`,
|
2168
|
+
transform: `
|
2169
|
+
translateX(${wobble}px)
|
2170
|
+
rotate(${rotation}deg)
|
2171
|
+
rotateX(${flipAngle}deg)
|
2172
|
+
scale(${scale})
|
2173
|
+
`,
|
2174
|
+
transformStyle: 'preserve-3d',
|
2175
|
+
opacity: particle.opacity,
|
2176
|
+
userSelect: 'none',
|
2177
|
+
position: 'relative',
|
2178
|
+
} },
|
2179
|
+
"\uD83C\uDF55",
|
2180
|
+
Math.random() > 0.5 && (React.createElement("div", { style: {
|
2181
|
+
position: 'absolute',
|
2182
|
+
fontSize: `${particle.size * 0.4}px`,
|
2183
|
+
top: `${10 + Math.random() * 30}%`,
|
2184
|
+
left: `${10 + Math.random() * 30}%`,
|
2185
|
+
transform: `rotate(${Math.random() * 360}deg)`,
|
2186
|
+
opacity: particle.opacity * 0.8,
|
2187
|
+
} }, ['🍅', '🧀', '🌶️'][Math.floor(Math.random() * 3)]))));
|
2188
|
+
};
|
2189
|
+
|
2190
|
+
const animations = {
|
2191
|
+
confetti: {
|
2192
|
+
createParticles: createConfettiParticles,
|
2193
|
+
renderParticle: renderConfettiParticle,
|
2194
|
+
},
|
2195
|
+
sparkles: {
|
2196
|
+
createParticles: createSparkleParticles,
|
2197
|
+
renderParticle: renderSparkleParticle,
|
2198
|
+
},
|
2199
|
+
hearts: {
|
2200
|
+
createParticles: createHeartParticles,
|
2201
|
+
renderParticle: renderHeartParticle,
|
2202
|
+
},
|
2203
|
+
fireworks: {
|
2204
|
+
createParticles: createFireworkParticles,
|
2205
|
+
renderParticle: renderFireworkParticle,
|
2206
|
+
},
|
2207
|
+
bubbles: {
|
2208
|
+
createParticles: createBubbleParticles,
|
2209
|
+
renderParticle: renderBubbleParticle,
|
2210
|
+
},
|
2211
|
+
stars: {
|
2212
|
+
createParticles: createStarParticles,
|
2213
|
+
renderParticle: renderStarParticle,
|
2214
|
+
},
|
2215
|
+
snow: {
|
2216
|
+
createParticles: createSnowParticles,
|
2217
|
+
renderParticle: renderSnowParticle,
|
2218
|
+
},
|
2219
|
+
emoji: {
|
2220
|
+
createParticles: createEmojiParticles,
|
2221
|
+
renderParticle: renderEmojiParticle,
|
2222
|
+
},
|
2223
|
+
coins: {
|
2224
|
+
createParticles: createCoinParticles,
|
2225
|
+
renderParticle: renderCoinParticle,
|
2226
|
+
},
|
2227
|
+
lightning: {
|
2228
|
+
createParticles: createLightningParticles,
|
2229
|
+
renderParticle: renderLightningParticle,
|
2230
|
+
},
|
2231
|
+
petals: {
|
2232
|
+
createParticles: createPetalParticles,
|
2233
|
+
renderParticle: renderPetalParticle,
|
2234
|
+
},
|
2235
|
+
aurora: {
|
2236
|
+
createParticles: createAuroraParticles,
|
2237
|
+
renderParticle: renderAuroraParticle,
|
2238
|
+
},
|
2239
|
+
fireflies: {
|
2240
|
+
createParticles: createFireflyParticles,
|
2241
|
+
renderParticle: renderFireflyParticle,
|
2242
|
+
},
|
2243
|
+
paint: {
|
2244
|
+
createParticles: createPaintParticles,
|
2245
|
+
renderParticle: renderPaintParticle,
|
2246
|
+
},
|
2247
|
+
music: {
|
2248
|
+
createParticles: createMusicParticles,
|
2249
|
+
renderParticle: renderMusicParticle,
|
2250
|
+
},
|
2251
|
+
balloons: {
|
2252
|
+
createParticles: createBalloonParticles,
|
2253
|
+
renderParticle: renderBalloonParticle,
|
2254
|
+
},
|
2255
|
+
galaxy: {
|
2256
|
+
createParticles: createGalaxyParticles,
|
2257
|
+
renderParticle: renderGalaxyParticle,
|
2258
|
+
},
|
2259
|
+
matrix: {
|
2260
|
+
createParticles: createMatrixParticles,
|
2261
|
+
renderParticle: renderMatrixParticle,
|
2262
|
+
},
|
2263
|
+
pixels: {
|
2264
|
+
createParticles: createPixelParticles,
|
2265
|
+
renderParticle: renderPixelParticle,
|
2266
|
+
},
|
2267
|
+
glitch: {
|
2268
|
+
createParticles: createGlitchParticles,
|
2269
|
+
renderParticle: renderGlitchParticle,
|
2270
|
+
},
|
2271
|
+
dice: {
|
2272
|
+
createParticles: createDiceParticles,
|
2273
|
+
renderParticle: renderDiceParticle,
|
2274
|
+
},
|
2275
|
+
levelup: {
|
2276
|
+
createParticles: createLevelUpParticles,
|
2277
|
+
renderParticle: renderLevelUpParticle,
|
2278
|
+
},
|
2279
|
+
magicdust: {
|
2280
|
+
createParticles: createMagicDustParticles,
|
2281
|
+
renderParticle: renderMagicDustParticle,
|
2282
|
+
},
|
2283
|
+
ghosts: {
|
2284
|
+
createParticles: createGhostParticles,
|
2285
|
+
renderParticle: renderGhostParticle,
|
2286
|
+
},
|
2287
|
+
crystals: {
|
2288
|
+
createParticles: createCrystalParticles,
|
2289
|
+
renderParticle: renderCrystalParticle,
|
2290
|
+
},
|
2291
|
+
dragons: {
|
2292
|
+
createParticles: createDragonParticles,
|
2293
|
+
renderParticle: renderDragonParticle,
|
2294
|
+
},
|
2295
|
+
runes: {
|
2296
|
+
createParticles: createRuneParticles,
|
2297
|
+
renderParticle: renderRuneParticle,
|
2298
|
+
},
|
2299
|
+
butterflies: {
|
2300
|
+
createParticles: createButterflyParticles,
|
2301
|
+
renderParticle: renderButterflyParticle,
|
2302
|
+
},
|
2303
|
+
leaves: {
|
2304
|
+
createParticles: createLeafParticles,
|
2305
|
+
renderParticle: renderLeafParticle,
|
2306
|
+
},
|
2307
|
+
rain: {
|
2308
|
+
createParticles: createRainParticles,
|
2309
|
+
renderParticle: renderRainParticle,
|
2310
|
+
},
|
2311
|
+
dandelion: {
|
2312
|
+
createParticles: createDandelionParticles,
|
2313
|
+
renderParticle: renderDandelionParticle,
|
2314
|
+
},
|
2315
|
+
bees: {
|
2316
|
+
createParticles: createBeeParticles,
|
2317
|
+
renderParticle: renderBeeParticle,
|
2318
|
+
},
|
2319
|
+
popcorn: {
|
2320
|
+
createParticles: createPopcornParticles,
|
2321
|
+
renderParticle: renderPopcornParticle,
|
2322
|
+
},
|
2323
|
+
champagne: {
|
2324
|
+
createParticles: createChampagneParticles,
|
2325
|
+
renderParticle: renderChampagneParticle,
|
2326
|
+
},
|
2327
|
+
candy: {
|
2328
|
+
createParticles: createCandyParticles,
|
2329
|
+
renderParticle: renderCandyParticle,
|
2330
|
+
},
|
2331
|
+
donuts: {
|
2332
|
+
createParticles: createDonutParticles,
|
2333
|
+
renderParticle: renderDonutParticle,
|
2334
|
+
},
|
2335
|
+
pizza: {
|
2336
|
+
createParticles: createPizzaParticles,
|
2337
|
+
renderParticle: renderPizzaParticle,
|
1007
2338
|
},
|
1008
2339
|
};
|
1009
2340
|
|