import { useEffect, useRef } from 'react'; export default function AmbientBackground() { const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); if (!ctx) return; let frame = 0; let width = (canvas.width = window.innerWidth); let height = (canvas.height = window.innerHeight); const onResize = () => { width = canvas.width = window.innerWidth; height = canvas.height = window.innerHeight; }; window.addEventListener('resize', onResize); const particles = Array.from({ length: 32 }, () => ({ x: Math.random() * width, y: Math.random() * height, size: Math.random() * 3 + 1.2, speedY: -(Math.random() * 0.4 + 0.15), speedX: (Math.random() - 0.5) * 0.2, opacity: Math.random() * 0.5 + 0.2, pulse: Math.random() * Math.PI, pulseSpeed: Math.random() * 0.03 + 0.01, })); const render = () => { ctx.clearRect(0, 0, width, height); for (const p of particles) { p.y += p.speedY; p.x += p.speedX; p.pulse += p.pulseSpeed; if (p.y < -10) { p.y = height + 10; p.x = Math.random() * width; } if (p.x < -10) p.x = width + 10; if (p.x > width + 10) p.x = -10; const a = p.opacity * (0.7 + 0.3 * Math.sin(p.pulse)); ctx.beginPath(); ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); ctx.fillStyle = `rgba(107, 56, 212, ${a * 0.45})`; ctx.fill(); } frame = requestAnimationFrame(render); }; render(); return () => { window.removeEventListener('resize', onResize); cancelAnimationFrame(frame); }; }, []); return (
); }