class ParticleBackground extends HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open' }); this.shadowRoot.innerHTML = ` `; const canvas = this.shadowRoot.getElementById('particles-canvas'); const ctx = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; // Particle system const particles = []; const particleCount = Math.floor(window.innerWidth * window.innerHeight / 10000); const colors = ['rgba(14, 165, 233, 0.6)', 'rgba(124, 58, 237, 0.6)', 'rgba(255, 255, 255, 0.8)']; // Create particles for (let i = 0; i < particleCount; i++) { particles.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, size: Math.random() * 3 + 1, speedX: Math.random() * 1 - 0.5, speedY: Math.random() * 1 - 0.5, color: colors[Math.floor(Math.random() * colors.length)] }); } // Animation loop const animate = () => { ctx.clearRect(0, 0, canvas.width, canvas.height); // Update and draw particles for (let i = 0; i < particles.length; i++) { const p = particles[i]; // Update position 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.size, 0, Math.PI * 2); ctx.fillStyle = p.color; ctx.fill(); // Draw connections for (let j = i + 1; j < particles.length; j++) { const p2 = particles[j]; const distance = Math.sqrt(Math.pow(p.x - p2.x, 2) + Math.pow(p.y - p2.y, 2)); if (distance < 100) { ctx.beginPath(); ctx.strokeStyle = `rgba(200, 200, 255, ${1 - distance/100})`; ctx.lineWidth = 0.5; ctx.moveTo(p.x, p.y); ctx.lineTo(p2.x, p2.y); ctx.stroke(); } } } requestAnimationFrame(animate); }; // Handle resize window.addEventListener('resize', () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }); animate(); } } customElements.define('particle-background', ParticleBackground);