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. 1

    Create the files

    Create `index.html`, `style.css` and `script.js` in the same folder.

  2. 2

    Paste the code

    Copy each file's source into its matching file.

  3. 3

    Open in the browser

    Open `index.html` in any modern browser.

Usage

  1. 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. 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();
Overview
Categoryanimations
Frameworkhtml
Difficultyadvanced
Licensemit
Versionv1.0.0
Features
  • requestAnimationFrame loop
  • DPR-aware canvas
  • Pauses on hidden tab automatically
Traits
  • ResponsiveYes
  • Dark modeYes
  • AccessibleYes
  • Production readyYes
Browser support
  • Chrome 90+
  • Firefox 90+
  • Safari 15+
  • Edge 90+

Related modules

Command Palette

Search modules and jump anywhere