webdevpuneet.com

Canvas Fireworks Physics — Free From-Scratch Particle Explosion

Canvas Fireworks Physics · Animations · Plain HTML, CSS & JS · Live preview

CategoryAnimations
TagsCanvas

Copy & paste

Source Code

<section class="fwp-wrap">
  <canvas class="fwp-canvas" id="fwpCanvas"></canvas>
  <div class="fwp-content">
    <span class="fwp-tag">canvas 2d · from-scratch physics</span>
    <h1>Happy launch day</h1>
    <p>Click anywhere to launch a rocket. Gravity, drag, and fade are hand-rolled — no particle library.</p>
  </div>
</section>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

From-scratch physics
Gravity and drag as plain constants — no particle library.
Two particle types
A Rocket constructor and a Particle constructor, each simple.
Exponential drag
Velocity multiplied by DRAG each frame for a natural decel.
Randomized fade rate
Per-particle decay means bursts fade unevenly, not all at once.
Ring-buffer trails
Each rocket keeps its last 6 positions, alpha-ramped.
Motion-blur clear
A translucent fill instead of clearRect leaves soft afterimages.
Click to launch
Rockets fire from the clicked x position.
Self-throttling auto-loop
A timer launches new rockets, capped by total particle count.

About this UI Snippet

Canvas Fireworks Physics — Gravity, Drag, and Fade From Scratch

Screenshot of the Canvas Fireworks Physics snippet rendered live

Most confetti and firework effects on the web reach for a particle library. This snippet is the opposite exercise: rockets, trails, explosions, gravity, air drag, and fade are all implemented directly against the 2D canvas API with two small object constructors and a handful of physics constants — useful both as a working effect and as a compact reference for how particle systems actually work under the hood.

Two kinds of particle

A Rocket starts at the bottom of the canvas with an upward velocity and a randomly chosen target height; a Particle is spawned only at the moment of explosion, with a random angle and speed so it flies outward in every direction from the burst point. Keeping these as two distinct, tiny constructors (rather than one particle type with a mode flag) keeps each one's update logic — arc-and-detonate versus radiate-and-fade — easy to read in isolation.

Real gravity and drag, not a lookup table

Every particle's vertical velocity increases by a constant GRAVITY each frame, exactly like a real projectile under constant acceleration. DRAG (0.985) is multiplied into both velocity components every frame, so particles lose speed exponentially rather than linearly — this is what makes a burst's outer edge decelerate and hang for a moment before gravity visibly takes over, matching how real fireworks debris behaves far more convincingly than a fixed-duration animation would.

Life as a countdown, not a timer

Rather than tracking each particle's remaining time with Date.now() comparisons, every particle has a life value starting at 1 that decrements by a random decay each frame, and ctx.globalAlpha is set directly from that value before drawing. Because decay is randomized per particle, a single burst fades out unevenly — some sparks visibly outlast others — instead of every particle in an explosion vanishing on the same frame.

A trail from a short history array

Each rocket keeps its own trail array of its last six positions, and every frame draws all of them with alpha increasing toward the most recent point. This is the same "ring buffer of recent positions, alpha-ramped" technique used for cursor trails and comet effects — it produces a convincing motion streak with no extra state beyond an array you push to and shift from.

Fading the whole canvas, not clearing it

Instead of ctx.clearRect, each frame paints a translucent rgba(4,5,12,0.22) rectangle over everything. That leaves a faint afterimage of the previous frame rather than a hard cut, giving trails and bursts a soft motion-blur quality for almost no extra code. Compare this from-scratch approach with the library-driven canvas confetti burst, or pair it with a starfield backdrop for a night-sky celebration scene.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA rocket auto-launches on load and the sky starts filling.
  2. 2
    Click anywhereA new rocket launches from that x position and climbs upward.
  3. 3
    Watch it detonateAt its random target height it explodes into 60-100 particles.
  4. 4
    Observe the fadeParticles lose speed to drag, fall to gravity, and fade at random rates.
  5. 5
    Let it auto-loopA timer launches new rockets every ~1.4s, capped by particle count.
  6. 6
    Tune the showChange GRAVITY, DRAG, COLORS, or the particle count per burst.

Real-world uses

Common Use Cases

Celebration and success states
Offer a bigger moment than a canvas confetti burst, with rockets that arc, explode and fade under gravity and drag.
New Year and holiday pages
Create a full-screen night sky where clicking launches rockets, built from plain constants with no particle library.
Product launch finales
Auto-loop fireworks behind a launch announcement, with randomised per-particle fade rates making each burst decay unevenly and naturally.
Event countdown endings
Trigger explode() manually when a timer hits zero, with exponential drag giving a natural deceleration after each burst.
Night-sky scene layers
Layer the effect over a starfield backdrop, using separate Rocket and Particle constructors that each stay simple to read.
Related: Canvas Noise Texture Background
See the Canvas Noise Texture Background for a related animations pattern worth pairing with this one.
Related: Cursor-Follow Underline Draw
See the Cursor-Follow Underline Draw for a related animations pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Everything here — rocket launch, arc, detonation, particle spawning, gravity, drag, and fade — is written directly against the 2D canvas API with two small constructors and a few numeric constants, with no external particle engine involved. The canvas confetti burst snippet wraps the canvas-confetti library instead; this one is the from-scratch version, useful when you want full control over the physics or want to see exactly how a particle system works.

Every frame, each particle's vx and vy are multiplied by DRAG (0.985), so velocity decays exponentially rather than dropping by a fixed amount. That produces a burst whose outer ring visibly slows and seems to hang for a moment before gravity pulls it down — much closer to how real firework debris moves through air resistance than a burst with no drag, which would keep expanding outward at a constant rate.

Each particle is given its own random decay value when it is created, and its life counter (starting at 1) drops by that amount every frame, directly driving ctx.globalAlpha. Because decay varies per particle, a single explosion does not vanish as one uniform block — some sparks linger visibly longer than others, the same way real embers burn out at different rates.

clearRect would wipe every trace of the previous frame instantly, leaving hard-edged dots with no sense of motion. Filling the canvas each frame with a low-alpha rgba(4,5,12,0.22) rectangle instead partially erases the previous frame, leaving a fading afterimage behind every moving trail and particle — a cheap way to get a motion-blur look without a shader or an offscreen buffer.

The auto-launch timer checks rockets.length + particles.length against a cap (260) before firing a new rocket, so the total particle count self-limits rather than growing without bound. Combined with particles being removed from the array once their life reaches zero, the scene reaches a steady-state particle count instead of accumulating indefinitely, which keeps frame time roughly constant during continuous play.