import { useState, useRef, useCallback } from 'react'; /** * Hook for managing particle effects * @param {React.RefObject} containerRef - Reference to container element * @param {boolean} isMobile - Whether the device is mobile * @returns {Object} Particle effects state and functions */ export const useParticleEffects = (containerRef, isMobile) => { const [particles, setParticles] = useState([]); const [popParticles, setPopParticles] = useState([]); const particleId = useRef(0); const isComponentMounted = useRef(true); // Handler for sparkle particles const handleCreateSparkleParticles = useCallback((x, y) => { const newParticles = createSparkleParticles(x, y, containerRef, isMobile, particleId); setParticles(prev => [...prev, ...newParticles]); setTimeout(() => { if (isComponentMounted.current) { setParticles(prev => prev.filter(p => !newParticles.find(np => np.id === p.id))); } }, 1000); }, [isMobile, containerRef]); // Handler for pop particles const handleCreatePopParticles = useCallback((x, y) => { const newParticles = createPopParticles(x, y, containerRef, isMobile, particleId); setPopParticles(prev => [...prev, ...newParticles]); setTimeout(() => { if (isComponentMounted.current) { setPopParticles(prev => prev.filter(p => !newParticles.find(np => np.id === p.id))); } }, 600); }, [isMobile, containerRef]); return { particles, popParticles, createSparkleParticles: handleCreateSparkleParticles, createPopParticles: handleCreatePopParticles, isComponentMounted }; }; /** * Particle effects component */ const ParticleEffects = ({ particles, popParticles }) => { return (
{/* Render sparkle particles */} {particles.map(particle => (
))} {/* Render pop particles */} {popParticles.map(particle => (
))}
); }; /** * Create sparkle particles * @param {number} x - X position * @param {number} y - Y position * @param {React.RefObject} containerRef - Reference to container element * @param {boolean} isMobile - Whether the device is mobile * @param {React.MutableRefObject} particleId - Reference to particle ID counter * @returns {Array} - Array of particle objects */ export const createSparkleParticles = (x, y, containerRef, isMobile, particleId) => { const newParticles = []; const numParticles = isMobile ? 8 : 12; // Get container position for relative positioning const containerRect = containerRef.current.getBoundingClientRect(); const relativeX = x - containerRect.left; const relativeY = y - containerRect.top; for (let i = 0; i < numParticles; i++) { const angle = (Math.PI * 2 * i) / numParticles; const velocity = 2 + Math.random() * 2; const size = isMobile ? 3 + Math.random() * 2 : 4 + Math.random() * 3; const tx = Math.cos(angle) * (30 + Math.random() * 20); const ty = Math.sin(angle) * (30 + Math.random() * 20); const rotation = Math.random() * 360; newParticles.push({ id: particleId.current++, x: relativeX, y: relativeY, size, style: { '--tx': `${tx}px`, '--ty': `${ty}px`, '--r': `${rotation}deg`, width: `${size}px`, height: `${size}px`, left: `${relativeX}px`, top: `${relativeY}px` } }); } return newParticles; }; /** * Create pop particles * @param {number} x - X position * @param {number} y - Y position * @param {React.RefObject} containerRef - Reference to container element * @param {boolean} isMobile - Whether the device is mobile * @param {React.MutableRefObject} particleId - Reference to particle ID counter * @returns {Array} - Array of particle objects */ export const createPopParticles = (x, y, containerRef, isMobile, particleId) => { const newParticles = []; const numParticles = isMobile ? 6 : 8; // Get container position for relative positioning const containerRect = containerRef.current.getBoundingClientRect(); const relativeX = x - containerRect.left; const relativeY = y - containerRect.top; for (let i = 0; i < numParticles; i++) { const angle = (Math.PI * 2 * i) / numParticles; const velocity = 3 + Math.random() * 2; const size = isMobile ? 4 + Math.random() * 3 : 6 + Math.random() * 4; const tx = Math.cos(angle) * (40 + Math.random() * 20); const ty = Math.sin(angle) * (40 + Math.random() * 20); const rotation = Math.random() * 360; newParticles.push({ id: particleId.current++, x: relativeX, y: relativeY, size, style: { '--tx': `${tx}px`, '--ty': `${ty}px`, '--r': `${rotation}deg`, width: `${size}px`, height: `${size}px`, left: `${relativeX}px`, top: `${relativeY}px` } }); } return newParticles; }; export default ParticleEffects;