Chapter 10

2D Canvas, Creative Coding & Particles

Immediate-mode rendering, particle systems, physics.

Canvas APIPixiJS v8Matter.js
The animation loop, particle systems, verlet integration, noise fields. PixiJS batches on the GPU; Matter.js simulates rigid bodies.

The DOM is great until you need a thousand things moving at once. When the count climbs into the hundreds or thousands — sparks, snow, confetti, fluid, fields of agents — you drop down to a <canvas> and drive every pixel yourself. This is creative coding: a loop, an array of particles, and a little physics.

Immediate mode vs retained mode

There are two ways a graphics system can work, and the distinction shapes everything you write.

Immediate mode

You own the frame. Each tick you clear the canvas and redraw the entire scene from scratch. There are no persistent objects — just your data and draw calls. The raw Canvas 2D API works this way. Total control, zero scene-graph overhead, but you implement hit-testing, layering and dirty-checking yourself.

Retained mode

You build a scene graph of persistent objects (sprites, nodes) and the library decides what to redraw. SVG, the DOM, and PixiJS are retained. More convenient and often GPU-batched, but you pay memory and indirection for every object you keep around.

Particle systems

A particle system is just an array of structs, each with a position, a velocity, and a life that ticks toward zero. An emitter spawns new ones; forces mutate velocities; dead particles are culled or recycled. That's the whole pattern — every fireworks, smoke, or starfield effect is a variation on it.

  • Emission — spawn N particles per second from a point/area, with randomized initial velocity.
  • Forces — add to velocity each frame: gravity (constant down), drag (multiply velocity by <1), a noise field (organic swirl), or attraction toward the cursor.
  • Integrationpos += vel * dt (semi-implicit Euler) is the cheap default.

Sandbox 1 — Canvas particles

Raw Canvas 2D, a typed-array particle store, and an rAF loop with devicePixelRatio scaling. Push the max particles slider toward 3,000 and watch the FPS meter — additive blending plus flat Float32Arrays keep it smooth. The cursor attracts or repels; clicking fires a burst.

Canvas particle sandbox — immediate-mode rAF loop live demo
60fps
dropped: 0

Move the cursor over the canvas to pull/push particles. Click for a firework burst. Live: 0

Sandbox 2 — Matter.js rigid bodies

Particles are point masses; sometimes you need things that collide and tumble. Matter.js is a 2D rigid-body engine: you create an Engine, a World, static walls, and dynamic bodies, then a Runner steps the simulation while Render draws it. A MouseConstraint lets you grab and throw bodies. Tune restitution (bounciness) and friction live.

Matter.js rigid-body sandbox live demo

Click empty space to add a box/circle. Drag to fling bodies around. Bodies: 0

Going GPU: PixiJS v8

The Canvas 2D API runs on the CPU; past a few thousand sprites it stalls. PixiJS is the standard retained-mode 2D renderer that batches sprites on the GPU, pushing into the tens of thousands. v8 is a single package with an async init — you await app.init(...) — and ships both a WebGPU and a WebGL renderer with automatic fallback.

import { Application } from 'pixi.js';

const app = new Application();
await app.init({ preference: 'webgpu', resizeTo: window });
document.body.appendChild(app.canvas);
WebGPU Newly available 2025
Chrome/Edge
Firefox
Safari

Chrome/Edge ship WebGPU broadly; Safari 26 enabled it by default; Firefox is rolling out (still behind a flag on some platforms). PixiJS auto-falls back to WebGL, so it's safe to set preference:'webgpu' today.

Playground — edit the loop

This is the bare pattern, yours to break. Edit update() to flip gravity, add drag (p.vx *= 0.98), or pull particles toward the center; edit draw() to change size, color, or blending. The low-alpha clear paints motion trails — set it to 1 for crisp dots. It re-runs as you type.