"use client"; import { useEffect, useRef } from "react"; interface NeuralNode { x: number; y: number; vx: number; vy: number; radius: number; } export function NeuralBackground() { const canvasRef = useRef(null); const nodesRef = useRef([]); const animRef = useRef(0); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; const resize = () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }; resize(); window.addEventListener("resize", resize); // Initialize nodes const nodeCount = 60; nodesRef.current = Array.from({ length: nodeCount }, () => ({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, vx: (Math.random() - 0.5) * 0.4, vy: (Math.random() - 0.5) * 0.4, radius: Math.random() * 2 + 1, })); const draw = () => { ctx.clearRect(0, 0, canvas.width, canvas.height); const nodes = nodesRef.current; // Update positions for (const node of nodes) { node.x += node.vx; node.y += node.vy; if (node.x < 0 || node.x > canvas.width) node.vx *= -1; if (node.y < 0 || node.y > canvas.height) node.vy *= -1; } // Draw connections const maxDist = 150; for (let i = 0; i < nodes.length; i++) { for (let j = i + 1; j < nodes.length; j++) { const dx = nodes[i].x - nodes[j].x; const dy = nodes[i].y - nodes[j].y; const dist = Math.sqrt(dx * dx + dy * dy); if (dist < maxDist) { const alpha = (1 - dist / maxDist) * 0.15; ctx.strokeStyle = `rgba(161, 161, 170, ${alpha})`; ctx.lineWidth = 0.5; ctx.beginPath(); ctx.moveTo(nodes[i].x, nodes[i].y); ctx.lineTo(nodes[j].x, nodes[j].y); ctx.stroke(); } } } // Draw nodes for (const node of nodes) { ctx.fillStyle = "rgba(161, 161, 170, 0.4)"; ctx.beginPath(); ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2); ctx.fill(); } animRef.current = requestAnimationFrame(draw); }; draw(); return () => { window.removeEventListener("resize", resize); cancelAnimationFrame(animRef.current); }; }, []); return ( ); }