'use client' import { useEffect, useRef } from 'react' interface Particle { x: number y: number size: number speed: number opacity: number } export default function ParticleBackground() { const canvasRef = useRef(null) const particlesRef = useRef([]) const frameRef = useRef(0) useEffect(() => { const canvas = canvasRef.current if (!canvas) return const ctx = canvas.getContext('2d') if (!ctx) return function resize() { canvas!.width = window.innerWidth canvas!.height = window.innerHeight } function initParticles() { const count = Math.min(150, Math.floor((window.innerWidth * window.innerHeight) / 8000)) particlesRef.current = Array.from({ length: count }, () => ({ x: Math.random() * canvas!.width, y: Math.random() * canvas!.height, size: Math.random() * 1.5 + 0.5, speed: Math.random() * 0.3 + 0.1, opacity: Math.random() * 0.5 + 0.1, })) } function animate() { if (!ctx || !canvas) return ctx.clearRect(0, 0, canvas.width, canvas.height) for (const p of particlesRef.current) { p.y -= p.speed if (p.y < -10) { p.y = canvas.height + 10 p.x = Math.random() * canvas.width } ctx.beginPath() ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2) ctx.fillStyle = `rgba(255, 255, 255, ${p.opacity})` ctx.fill() } frameRef.current = requestAnimationFrame(animate) } resize() initParticles() animate() window.addEventListener('resize', () => { resize() initParticles() }) return () => { cancelAnimationFrame(frameRef.current) window.removeEventListener('resize', resize) } }, []) return ( ) }