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 = this.clientWidth; canvas.height = this.clientHeight; // Particle system const particles = []; const particleCount = Math.floor(canvas.width * canvas.height / 10000); // Particle constructor function Particle() { this.x = Math.random() * canvas.width; this.y = Math.random() * canvas.height; this.vx = -0.5 + Math.random(); this.vy = -0.5 + Math.random(); this.radius = 1 + Math.random() * 2; this.color = `rgba(103, 78, 234, ${Math.random() * 0.6})`; } // Initialize particles for (let i = 0; i < particleCount; i++) { particles.push(new Particle()); } function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); for (let i = 0; i < particles.length; i++) { const p = particles[i]; // Update position p.x += p.vx; p.y += p.vy; // Wrap around screen if (p.x < 0) p.x = canvas.width; if (p.x > canvas.width) p.x = 0; if (p.y < 0) p.y = canvas.height; if (p.y > canvas.height) p.y = 0; // Draw particle ctx.beginPath(); ctx.arc(p.x, p.y, p.radius, 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(103, 78, 234, ${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 = this.clientWidth; canvas.height = this.clientHeight; }); animate(); } } customElements.define('particle-background', ParticleBackground);