class FireworksAnimation extends HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open' }); this.shadowRoot.innerHTML = ` `; const canvas = this.shadowRoot.getElementById('fireworks'); const ctx = canvas.getContext('2d'); function resize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } resize(); window.addEventListener('resize', resize); let rockets = []; let particles = []; let lastLaunch = Date.now(); class Rocket { constructor() { this.x = Math.random() * canvas.width; this.y = canvas.height; this.vy = -8 - Math.random() * 3; this.exploded = false; this.color = `hsl(${Math.random() * 60 + 0}, 100%, 50%)`; } } class Particle { constructor(x, y, color) { this.x = x; this.y = y; const angle = Math.random() * Math.PI * 2; const speed = Math.random() * 5 + 3; this.vx = Math.cos(angle) * speed; this.vy = Math.sin(angle) * speed; this.life = 120; this.alpha = 1; this.color = color; } update() { this.x += this.vx; this.y += this.vy; this.vy += 0.04; // gravity this.life--; this.alpha = this.life / 120; } draw(ctx) { ctx.beginPath(); ctx.arc(this.x, this.y, 2, 0, Math.PI * 2); ctx.fillStyle = `${this.color.replace(')', `, ${this.alpha})`).replace('hsl', 'hsla')}`; ctx.shadowBlur = 10; ctx.shadowColor = this.color; ctx.fill(); } } function explode(x, y, color) { const count = 180; for (let i = 0; i < count; i++) { const angle = (Math.PI * 2) * (i / count); const speed = Math.random() * 5 + 3; particles.push(new Particle(x, y, color)); } } function launchRocket() { rockets.push(new Rocket()); lastLaunch = Date.now(); } function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); // Launch new rocket randomly if (Date.now() - lastLaunch > 2000 + Math.random() * 3000) { launchRocket(); } // Update rockets rockets.forEach((rocket, i) => { rocket.y += rocket.vy; // Draw rocket trail ctx.beginPath(); ctx.moveTo(rocket.x, rocket.y + 30); ctx.lineTo(rocket.x, rocket.y); ctx.strokeStyle = "rgba(255,255,255,0.8)"; ctx.lineWidth = 2; ctx.stroke(); // Check for explosion if (rocket.y < canvas.height * (0.3 + Math.random() * 0.3)) { explode(rocket.x, rocket.y, rocket.color); rockets.splice(i, 1); } }); // Update particles particles.forEach((p, i) => { p.update(); p.draw(ctx); if (p.life <= 0) particles.splice(i, 1); }); requestAnimationFrame(animate); } // Initial launch and set timeout to remove element setTimeout(launchRocket, 500); animate(); setTimeout(() => { this.remove(); }, 6000); } } customElements.define('fireworks-animation', FireworksAnimation);