diff options
Diffstat (limited to 'app/components/WaveEffect.tsx')
| -rw-r--r-- | app/components/WaveEffect.tsx | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/app/components/WaveEffect.tsx b/app/components/WaveEffect.tsx new file mode 100644 index 0000000..853e25e --- /dev/null +++ b/app/components/WaveEffect.tsx @@ -0,0 +1,71 @@ +"use client" + +import type React from "react" +import { useRef, useEffect } from "react" + +interface WaveEffectProps { + color: string + triggerWave: boolean + mousePosition: { x: number; y: number } +} + +const WaveEffect: React.FC<WaveEffectProps> = ({ color, triggerWave, mousePosition }) => { + const canvasRef = useRef<HTMLCanvasElement>(null) + + useEffect(() => { + const canvas = canvasRef.current + if (!canvas) return + + const ctx = canvas.getContext("2d") + if (!ctx) return + + canvas.width = window.innerWidth + canvas.height = window.innerHeight + + let animationFrameId: number + const waves: { x: number; y: number; radius: number; opacity: number }[] = [] + + const createWave = (x: number, y: number) => { + waves.push({ x, y, radius: 0, opacity: 0.5 }) + } + + const drawWaves = () => { + ctx.clearRect(0, 0, canvas.width, canvas.height) + + waves.forEach((wave, index) => { + ctx.beginPath() + ctx.arc(wave.x, wave.y, wave.radius, 0, Math.PI * 2) + ctx.strokeStyle = `rgba(${color}, ${wave.opacity})` + ctx.lineWidth = 2 + ctx.stroke() + + // Slow down the expansion rate + wave.radius += 1 + + // Slow down the fade-out rate + wave.opacity -= 0.005 + + if (wave.opacity <= 0) { + waves.splice(index, 1) + } + }) + + animationFrameId = requestAnimationFrame(drawWaves) + } + + if (triggerWave) { + createWave(mousePosition.x, mousePosition.y) + } + + drawWaves() + + return () => { + cancelAnimationFrame(animationFrameId) + } + }, [color, triggerWave, mousePosition]) + + return <canvas ref={canvasRef} className="absolute top-0 left-0 w-full h-full pointer-events-none" /> +} + +export default WaveEffect + |
