// ===== MOLECULAR PARTICLE ANIMATION ===== // Create a canvas background const canvas = document.createElement('canvas'); canvas.id = 'moleculeCanvas'; document.body.appendChild(canvas); const ctx = canvas.getContext('2d'); // Resize canvas to full window function resizeCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } window.addEventListener('resize', resizeCanvas); resizeCanvas(); // Create particles let particles = []; const numParticles = 80; for (let i = 0; i < numParticles; i++) { particles.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, radius: Math.random() * 4 + 1, color: Math.random() > 0.5 ? '#00ff88' : '#ffaa00', speedX: (Math.random() - 0.5) * 1.5, speedY: (Math.random() - 0.5) * 1.5 }); } // Animation loop function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); // Draw and move particles particles.forEach((p, index) => { p.x += p.speedX; p.y += p.speedY; // Bounce off edges if (p.x < 0 || p.x > canvas.width) p.speedX *= -1; if (p.y < 0 || p.y > canvas.height) p.speedY *= -1; // Draw particle ctx.beginPath(); ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2); ctx.fillStyle = p.color; ctx.fill(); // Connect lines if particles are close for (let j = index + 1; j < particles.length; j++) { let dx = particles[j].x - p.x; let dy = particles[j].y - p.y; let distance = Math.sqrt(dx * dx + dy * dy); if (distance < 120) { ctx.beginPath(); ctx.moveTo(p.x, p.y); ctx.lineTo(particles[j].x, particles[j].y); ctx.strokeStyle = p.color === '#00ff88' ? '#00ff88aa' : '#ffaa00aa'; ctx.lineWidth = 0.5; ctx.stroke(); } } }); requestAnimationFrame(animate); } animate();