library / celebration / fizzy-sparks
live - 60fps 1920 x 1080
fizzy-sparks.html - self-contained
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Fizzy Sparks</title>
    <style>
      /*
        Fizzy Sparks
        ------------
        This interactive canvas spawns small, glowing sparks wherever the
        user moves or clicks the mouse.  Each spark travels in a random
        direction and fades out over time.  The effect approximates the
        original CodePen's fizzy sparks animation using only plain
        JavaScript and the Canvas API.
      */
      html, body {
        margin: 0;
        padding: 0;
        height: 100%;
        overflow: hidden;
        background: #000;
        cursor: crosshair;
      }
      canvas {
        display: block;
      }
    </style>
  </head>
  <body>
    <canvas id="sparks"></canvas>
    <script>
      (function() {
        const canvas = document.getElementById('sparks');
        const ctx    = canvas.getContext('2d');
        function resize() {
          canvas.width  = window.innerWidth;
          canvas.height = window.innerHeight;
        }
        window.addEventListener('resize', resize);
        resize();

        // Particle class representing a single spark.
        class Spark {
          constructor(x, y) {
            this.x     = x;
            this.y     = y;
            const angle= Math.random() * Math.PI * 2;
            const speed= 2 + Math.random() * 3;
            this.vx    = Math.cos(angle) * speed;
            this.vy    = Math.sin(angle) * speed;
            this.life  = 40 + Math.floor(Math.random() * 20);
            this.age   = 0;
            this.radius= 2 + Math.random() * 3;
            // Choose a bright, random colour.
            const hue = Math.floor(Math.random() * 360);
            this.colour = `hsl(${hue}, 80%, 60%)`;
          }
          update() {
            this.x += this.vx;
            this.y += this.vy;
            // Apply a small amount of friction.
            this.vx *= 0.98;
            this.vy *= 0.98;
            // Gravity to pull sparks downwards.
            this.vy += 0.05;
            this.age++;
          }
          draw(ctx) {
            const alpha = 1 - this.age / this.life;
            ctx.fillStyle = this.colour;
            ctx.globalAlpha = alpha;
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
            ctx.fill();
            ctx.globalAlpha = 1;
          }
          isDead() {
            return this.age >= this.life;
          }
        }

        const sparks = [];
        function spawn(x, y, count) {
          for (let i = 0; i < count; i++) {
            sparks.push(new Spark(x, y));
          }
        }
        // Spawn sparks on mouse movement and clicks.
        let lastSpawn = 0;
        document.addEventListener('mousemove', (e) => {
          const now = Date.now();
          if (now - lastSpawn > 50) {
            spawn(e.clientX, e.clientY, 5);
            lastSpawn = now;
          }
        });
        document.addEventListener('click', (e) => {
          spawn(e.clientX, e.clientY, 20);
        });

        function animate() {
          // Draw a translucent black rectangle to create trails.
          ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
          ctx.fillRect(0, 0, canvas.width, canvas.height);
          // Update and draw each spark.
          for (let i = sparks.length - 1; i >= 0; i--) {
            const s = sparks[i];
            s.update();
            s.draw(ctx);
            if (s.isDead()) {
              sparks.splice(i, 1);
            }
          }
          requestAnimationFrame(animate);
        }
        animate();
      })();
    </script>
  </body>
</html>

About this animation

Rising bubbles and sparks, great for success states.

Under the hood

Upward Buoyancy Physics

Sparks behave with negative gravity (buoyancy). Spawned at the bottom of the screen, they rise upwards, jittering left and right mapped to sine waves, before fading out via globalAlpha at the top of the viewport.

Source Code
Source copied
Partner hosting options for the copied effect:
Vercel Netlify Hostinger