Skip to the page
TACTILE UI

How the Chladni Plate works

A black square plate on a shaker, strewn with sand, with a frequency knob. Turn the knob onto a resonance and the sand runs off the parts that move and piles up on the lines that stand still, so the plate draws its own figure. I didn't draw any of the figures. This page is how the plate finds them.

Written 29 September 2026. Vanilla ES modules and canvas 2D, no dependencies, 11.4 KB gzipped, 8 tests. The physics is DOM-free, so the tests run it in Node.

The plate's modes

A square plate with free edges has natural shapes it likes to vibrate in, its modes. I use the classical approximation for a free square plate, with u and v running from 0 to 1 across it:

ψ(n, m) = cos(nπu)·cos(mπv) + cos(mπu)·cos(nπv)

The shaker drives the plate at its centre, and a centre drive only excites the modes that move at the centre: n and m both even. So the plate has modes like (0, 2), (2, 4), (0, 6), (4, 6) and so on, up to m = 12. Each one rings at its own frequency, 52 Hz × (n² + m²). (0, 6) is at 1,872 Hz; (4, 6) is at 2,704 Hz.

How hard each mode answers

A mode doesn't only move at its exact frequency. It answers any drive, weakly far away and strongly near its resonance, like a damped oscillator:

export function response(f, fm, Q = 50) {
  const r = f / fm;
  return 1 / Math.sqrt((1 - r * r) ** 2 + (r / Q) ** 2);
}

At the knob's frequency, every mode gets that weight, and the plate's motion is the sum of the modes, weighted, on a 96 × 96 grid. That runs only when the frequency changes, not every frame. On a resonance one mode dominates and its shape is the figure. Between two resonances you get a mix, and the plate barely moves.

The sand

The sand is 9,000 grains by default. Each frame, every grain is kicked in proportion to how much the plate moves under it, in a random direction, and drifts down the slope of the plate's motion toward the places where it doesn't move. A grain where the plate is still stays put. So the sand leaves the antinodes and collects on the nodal lines, and the figure appears in a second or two.

The strength of the kick is the square of how hard the plate is ringing, the energy it passes to the sand. Off a resonance the sand just shivers. On one it dances. Grains that reach an edge bounce back rather than fall off.

All 9,000 are counted into one ImageData each frame, at the plate's CSS size, so the sand costs one putImageData however many grains there are. The plate itself is drawn once per size.

The knob

The knob is a real slider in hertz on a log scale, from 150 Hz to 8 kHz, and it tells a screen reader both the frequency and the mode it's ringing in. Under your hand each resonance is a detent. Arrow keys fine-tune, and Page Up and Page Down jump to the next resonance. A finger on the plate pours a pinch more sand. When nothing moves, the loop sleeps.

What it isn't

It's not a finite-element simulation of a real plate. The mode shapes are the textbook approximation, the plate is ideal, and the resonances are sharper and cleaner than a real one's. It's close enough that the figures are the right figures, which is what I wanted.

Play with it on the object page. The source comes with a Pass.