File size: 2,693 Bytes
42da440 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | import React, { useState, useEffect, useRef } from 'react';
import { motion } from 'framer-motion';
const random = (min, max) => Math.random() * (max - min) + min;
const Particle = ({ id, color, size, duration }) => {
const angle = random(0, Math.PI * 2);
const radius = random(40, 85); // How far particles travel (Increased)
const endX = Math.cos(angle) * radius;
const endY = Math.sin(angle) * radius;
return (
<motion.div
className="absolute rounded-full pointer-events-none"
style={{
backgroundColor: color,
width: size,
height: size,
left: '50%', // Start at center
top: '50%',
translateX: '-50%', // Adjust for centering
translateY: '-50%',
}}
initial={{ opacity: 1, scale: 1 }}
animate={{
x: endX,
y: endY,
scale: 0, // Shrink to disappear
opacity: 0,
}}
transition={{ duration: duration, ease: 'easeOut' }}
/>
);
};
const ButtonParticles = ({ trigger, color = '#ffffff', count = 8, size = 3.5, duration = 0.45 }) => {
const [particles, setParticles] = useState([]);
console.log(`ButtonParticles: Rendered. Current trigger=${trigger}, particles=${particles.length}`);
useEffect(() => {
console.log(`ButtonParticles: useEffect triggered. trigger=${trigger}`);
if (trigger > 0) { // trigger increments on each click
console.log(`ButtonParticles: Trigger > 0 (${trigger}). Generating ${count} particles.`);
const newParticles = Array.from({ length: count }).map((_, i) => ({
id: `${trigger}-${i}`, // Unique key based on trigger and index
color,
size,
duration,
}));
setParticles(newParticles);
console.log("ButtonParticles: Particles state updated:", newParticles);
// Optional: Clear particles after animation - not strictly needed as they animate to opacity 0
const timer = setTimeout(() => {
console.log(`ButtonParticles: Clearing particles after ${duration}s timeout.`);
setParticles([]);
}, duration * 1000); // Clear particles after animation
return () => {
console.log("ButtonParticles: useEffect cleanup running.");
clearTimeout(timer)
};
}
}, [trigger, color, count, size, duration]);
// Render only the particles currently animating
return (
<>
{particles.map(p => (
<React.Fragment key={p.id}> {/* Use Fragment to add log without extra div */}
{/* {console.log(`ButtonParticles: Rendering Particle id=${p.id}`)} */}
<Particle key={p.id} {...p} />
</React.Fragment>
))}
</>
);
};
export default ButtonParticles; |