htmladvancedmit
Fireworks
Automatic exploding fireworks.
2.4k2.4k712422
About this module
Rockets launch from the bottom and burst into radially expanding particles with gravity and fade.
#canvas#2d#fireworks#particles#burst
Source code
Installation
- 1
Create the files
Create `index.html`, `style.css` and `script.js` in the same folder.
- 2
Paste the code
Copy each file's source into its matching file.
- 3
Open in the browser
Open `index.html` in any modern browser.
Usage
- 1
Copy the HTML
Paste the canvas markup where you need it.
<link rel="stylesheet" href="style.css" /> <script src="script.js"></script> <div class="mh-canvas-wrap" style="background:#0a0e18"> <canvas id="mh-canvas"></canvas> <span class="mh-canvas-label">FIREWORKS</span> </div> - 2
Wire up the script
Include `script.js` before the closing body tag.
const canvas = document.getElementById("mh-canvas"); const ctx = canvas.getContext("2d"); let w, h, dpr = Math.min(window.devicePixelRatio || 1, 2); const rockets = [], sparks = []; const COLORS = ["#fbbf24", "#f472b6", "#22d3ee", "#a3e635", "#f87171", "#a78bfa"]; function resize() { const rect = canvas.parentElement.getBoundingClientRect(); w = rect.width; h = rect.height; canvas.width = w * dpr; canvas.height = h * dpr; canvas.style.width = w + "px"; canvas.style.height = h + "px"; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); } function launch() { rockets.push({ x: Math.random() * w, y: h, vy: -(Math.random() * 5 + 5), targetY: Math.random() * h * 0.5, color: COLORS[Math.floor(Math.random() * COLORS.length)] }); } function burst(x, y, color) { const n = 60; for (let i = 0; i < n; i++) { const a = (i / n) * Math.PI * 2; const sp = Math.random() * 3 + 1.5; sparks.push({ x, y, vx: Math.cos(a) * sp, vy: Math.sin(a) * sp, life: 1, color }); } } function tick() { ctx.fillStyle = "rgba(10,14,24,0.25)"; ctx.fillRect(0, 0, w, h); for (let i = rockets.length - 1; i >= 0; i--) { const r = rockets[i]; r.y += r.vy; ctx.beginPath(); ctx.arc(r.x, r.y, 2, 0, Math.PI * 2); ctx.fillStyle = r.color; ctx.fill(); if (r.y <= r.targetY) { burst(r.x, r.y, r.color); rockets.splice(i, 1); } } for (let i = sparks.length - 1; i >= 0; i--) { const s = sparks[i]; s.x += s.vx; s.y += s.vy; s.vy += 0.05; s.vx *= 0.98; s.life -= 0.012; if (s.life <= 0) { sparks.splice(i, 1); continue; } ctx.beginPath(); ctx.arc(s.x, s.y, 1.6, 0, Math.PI * 2); ctx.globalAlpha = Math.max(0, s.life); ctx.fillStyle = s.color; ctx.fill(); ctx.globalAlpha = 1; } requestAnimationFrame(tick); } resize(); window.addEventListener("resize", resize); setInterval(() => { if (rockets.length < 4) launch(); }, 500); tick();