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);