← all components
#03

Particle explosion button

A button that fires a burst of colorful particles from its center on click, each flying out at a random angle and falling with gravity, drawn on a canvas. Available in React or plain HTML, Canvas and JavaScript.

ReactCanvasJSHTML
// LIVE DEMO
share this component →FacebookX / TwitterLinkedIn
// THE CODE
React
"use client";
import { useRef } from "react";

const colors = ["#38bdf8", "#818cf8", "#f472b6", "#34d399", "#fbbf24"];

export default function ParticleBurstButton() {
  const canvasRef = useRef(null), btnRef = useRef(null);

  function burst() {
    const canvas = canvasRef.current, btn = btnRef.current, ctx = canvas.getContext("2d");
    if (matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    const DPR = Math.min(devicePixelRatio || 1, 2);
    const rect = canvas.getBoundingClientRect(), br = btn.getBoundingClientRect();
    canvas.width = rect.width * DPR; canvas.height = rect.height * DPR; ctx.setTransform(DPR,0,0,DPR,0,0);
    const cx = br.left - rect.left + br.width/2, cy = br.top - rect.top + br.height/2;
    const parts = Array.from({ length: 46 }, () => {
      const a = Math.random()*Math.PI*2, sp = 2 + Math.random()*7;
      return { x:cx, y:cy, vx:Math.cos(a)*sp, vy:Math.sin(a)*sp-2,
        r:2+Math.random()*3, color:colors[(Math.random()*colors.length)|0], life:1 };
    });
    (function tick() {
      ctx.clearRect(0,0,rect.width,rect.height);
      let alive = false;
      for (const p of parts) {
        if (p.life <= 0) continue; alive = true;
        p.vy += .18; p.vx *= .99; p.x += p.vx; p.y += p.vy; p.life -= .016;
        ctx.globalAlpha = Math.max(0, p.life); ctx.fillStyle = p.color;
        ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, 7); ctx.fill();
      }
      ctx.globalAlpha = 1;
      if (alive) requestAnimationFrame(tick); else ctx.clearRect(0,0,rect.width,rect.height);
    })();
  }

  return (
    <div className="relative inline-block">
      <canvas ref={canvasRef} className="absolute inset-0 w-full h-full pointer-events-none" />
      <button ref={btnRef} onClick={burst}
        className="relative z-10 px-8 py-3.5 rounded-2xl font-bold text-black
          bg-gradient-to-br from-sky-400 to-indigo-400 active:scale-95 transition">
        Click to explode
      </button>
    </div>
  );
}
// HOW IT WORKS
  • 01On click, ~46 particles spawn at the button's center with a random angle and speed.
  • 02Each frame applies gravity and drag to every particle, then draws it fading out over its life.
  • 03It all runs on an overlay canvas so the button stays crisp; the loop stops itself once every particle has faded.
Want a custom component for your product?
Let's build it →