"use client"; import { useEffect, useRef } from "react"; const ParticleBackground = () => { const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; // Set canvas size const resize = () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }; resize(); window.addEventListener("resize", resize); // Particle system const particles: Array<{ x: number; y: number; vx: number; vy: number; radius: number; color: string; }> = []; const colors = ["#00ffff", "#9d00ff", "#ff00ff", "#00ff9d"]; // Create particles for (let i = 0; i < 80; i++) { particles.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, vx: (Math.random() - 0.5) * 0.5, vy: (Math.random() - 0.5) * 0.5, radius: Math.random() * 2 + 0.5, color: colors[Math.floor(Math.random() * colors.length)], }); } // Mouse interaction let mouseX = canvas.width / 2; let mouseY = canvas.height / 2; const onMouseMove = (e: MouseEvent) => { mouseX = e.clientX; mouseY = e.clientY; }; window.addEventListener("mousemove", onMouseMove); // Animation loop const animate = () => { ctx.clearRect(0, 0, canvas.width, canvas.height); // Draw connecting lines for (let i = 0; i < particles.length; i++) { for (let j = i + 1; j < particles.length; j++) { const dx = particles[i].x - particles[j].x; const dy = particles[i].y - particles[j].y; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < 150) { ctx.beginPath(); ctx.strokeStyle = `rgba(0, 224, 255, ${0.2 * (1 - distance / 150)})`; ctx.lineWidth = 0.5; ctx.moveTo(particles[i].x, particles[i].y); ctx.lineTo(particles[j].x, particles[j].y); ctx.stroke(); } } } // Update and draw particles particles.forEach((p) => { // Move particle p.x += p.vx; p.y += p.vy; // Bounce off edges if (p.x < 0 || p.x > canvas.width) p.vx *= -1; if (p.y < 0 || p.y > canvas.height) p.vy *= -1; // Attract to mouse const dx = mouseX - p.x; const dy = mouseY - p.y; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < 200) { p.vx += dx * 0.0001; p.vy += dy * 0.0001; } // Limit velocity const speed = Math.sqrt(p.vx * p.vx + p.vy * p.vy); if (speed > 1) { p.vx = (p.vx / speed) * 1; p.vy = (p.vy / speed) * 1; } // Draw particle ctx.beginPath(); const gradient = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.radius * 3); gradient.addColorStop(0, p.color); gradient.addColorStop(1, "transparent"); ctx.fillStyle = gradient; ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2); ctx.fill(); }); requestAnimationFrame(animate); }; const animationId = requestAnimationFrame(animate); // Cleanup return () => { window.removeEventListener("resize", resize); window.removeEventListener("mousemove", onMouseMove); cancelAnimationFrame(animationId); }; }, []); return ( ); }; export default ParticleBackground;