Spaces:
Sleeping
Sleeping
| import React, { useEffect, useRef } from 'react'; | |
| const NeuralBackground: React.FC = () => { | |
| const canvasRef = useRef<HTMLCanvasElement>(null); | |
| useEffect(() => { | |
| const canvas = canvasRef.current; | |
| if (!canvas) return; | |
| const ctx = canvas.getContext('2d'); | |
| if (!ctx) return; | |
| let animationFrameId: number; | |
| let particles: Particle[] = []; | |
| const resize = () => { | |
| canvas.width = window.innerWidth; | |
| canvas.height = window.innerHeight; | |
| }; | |
| class Particle { | |
| x: number; y: number; vx: number; vy: number; | |
| constructor() { | |
| this.x = Math.random() * canvas!.width; | |
| this.y = Math.random() * canvas!.height; | |
| this.vx = (Math.random() - 0.5) * 0.4; | |
| this.vy = (Math.random() - 0.5) * 0.4; | |
| } | |
| update() { | |
| this.x += this.vx; | |
| this.y += this.vy; | |
| if (this.x < 0 || this.x > canvas!.width) this.vx *= -1; | |
| if (this.y < 0 || this.y > canvas!.height) this.vy *= -1; | |
| } | |
| draw() { | |
| ctx!.beginPath(); | |
| ctx!.arc(this.x, this.y, 1.2, 0, Math.PI * 2); | |
| ctx!.fillStyle = 'rgba(99, 102, 241, 0.4)'; | |
| ctx!.fill(); | |
| } | |
| } | |
| const init = () => { | |
| particles = Array.from({ length: 100 }, () => new Particle()); | |
| }; | |
| const drawLines = () => { | |
| 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 dist = Math.sqrt(dx * dx + dy * dy); | |
| if (dist < 150) { | |
| ctx!.beginPath(); | |
| ctx!.strokeStyle = `rgba(99, 102, 241, ${0.15 * (1 - dist / 150)})`; | |
| ctx!.lineWidth = 0.8; | |
| ctx!.moveTo(particles[i].x, particles[i].y); | |
| ctx!.lineTo(particles[j].x, particles[j].y); | |
| ctx!.stroke(); | |
| } | |
| } | |
| } | |
| }; | |
| const render = () => { | |
| ctx.clearRect(0, 0, canvas.width, canvas.height); | |
| particles.forEach(p => { | |
| p.update(); | |
| p.draw(); | |
| }); | |
| drawLines(); | |
| animationFrameId = requestAnimationFrame(render); | |
| }; | |
| window.addEventListener('resize', resize); | |
| resize(); | |
| init(); | |
| render(); | |
| return () => { | |
| window.removeEventListener('resize', resize); | |
| cancelAnimationFrame(animationFrameId); | |
| }; | |
| }, []); | |
| return ( | |
| <canvas | |
| ref={canvasRef} | |
| style={{ | |
| position: 'fixed', | |
| top: 0, | |
| left: 0, | |
| zIndex: -1, | |
| background: 'transparent', | |
| pointerEvents: 'none' | |
| }} | |
| /> | |
| ); | |
| }; | |
| export default NeuralBackground; | |