|
import { useState, useRef, useCallback } from 'react'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const useParticleEffects = (containerRef, isMobile) => { |
|
const [particles, setParticles] = useState([]); |
|
const [popParticles, setPopParticles] = useState([]); |
|
const particleId = useRef(0); |
|
const isComponentMounted = useRef(true); |
|
|
|
|
|
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]); |
|
|
|
|
|
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 |
|
}; |
|
}; |
|
|
|
|
|
|
|
|
|
const ParticleEffects = ({ particles, popParticles }) => { |
|
return ( |
|
<div className="absolute inset-0 pointer-events-none overflow-hidden"> |
|
{/* Render sparkle particles */} |
|
{particles.map(particle => ( |
|
<div |
|
key={particle.id} |
|
className="particle" |
|
style={particle.style} |
|
/> |
|
))} |
|
|
|
{/* Render pop particles */} |
|
{popParticles.map(particle => ( |
|
<div |
|
key={particle.id} |
|
className="pop-particle" |
|
style={particle.style} |
|
/> |
|
))} |
|
</div> |
|
); |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const createSparkleParticles = (x, y, containerRef, isMobile, particleId) => { |
|
const newParticles = []; |
|
const numParticles = isMobile ? 8 : 12; |
|
|
|
|
|
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; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const createPopParticles = (x, y, containerRef, isMobile, particleId) => { |
|
const newParticles = []; |
|
const numParticles = isMobile ? 6 : 8; |
|
|
|
|
|
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; |