Chladni Plate
chladni-plateVisualizersDrive a metal plate at a frequency and sand on it collects along the nodal lines — the places that are not moving. This draws that figure for any set of frequencies, either as a particle simulation settling onto the nodes over a few seconds or as the standing wave rendered directly as a field, on a square or circular plate. It is parameter-driven and touches no audio: feed it held notes, an analyser's peak bin, or a slider. All the physics lives in the chladni-formulas library — pure functions with unit tests pinning their numerics — so this component is only the renderer.
Particles settling on the nodal lines, and the same modes rendered as a field on a circular plate. Drag the slider to retune the plate.
Install
Copies the source into your project. Anything it depends on comes with it.
$ npx shadcn add @syntho-ui/chladni-platePulls in
First time? Add the registry to your components.json once:
{
"registries": {
"@syntho-ui": "https://engine.syntho.app/r/{name}.json"
}
}Usage
Controlled or uncontrolled, whichever suits the surrounding state.
import { ChladniPlate } from "@/components/ui/chladni-plate"
<ChladniPlate frequencies={heldNotes} variant="particles" height={260} />Props
| Prop | Type | Default | Description |
|---|---|---|---|
| frequencies | number[] | [440] | The frequencies driving the plate, in Hz. Each maps to a mode pair and the patterns superpose. |
| modes | { m: number; n: number } | — | Mode numbers directly, bypassing the frequency mapping. Wins over frequencies when set. |
| variant | "particles" | "field" | "particles" | Sand finding the nodes over time, or the standing wave drawn as a heatmap. |
| plateShape | "square" | "circular" | "square" | Circular masks the pattern to the inscribed disc and outlines it. |
| particleCount | number | 2000 | How many particles to simulate. Only read by the particle variant. |
| vibrationStrength | number | 0.02 | Random-walk scale. Higher settles faster but blurs the lines. |
| resolution | number | 80 | Field sampling grid per axis. Only read by the field variant. |
| a / b | number | 1 / 1 | Amplitude coefficients of the mode and its transpose. |
| color | string | — | Particle / nodal-line colour. Defaults to the --uikit-accent token. |
| size / height | number | string | "100%" / 260 | The canvas box. The plate is inscribed square and centred inside it. |
| paused | boolean | false | Stop the animation and hold the current pattern. |
Interaction
- Drag with pointer capture, so the gesture keeps tracking past the edge of the control.
- Shift while dragging for a fine pass; release it mid-gesture and coarse tracking resumes.
- Double-click resets to
defaultValue. - Arrow keys step normally, Shift+arrow steps finely, PageUp/PageDown jump by ten, Home/End go to the extremes.
- Proper
sliderandswitchroles with livearia-valuetext, so a screen reader announces the formatted value rather than the raw number. - The scroll wheel adjusts the value while the pointer is over the control; stepped ranges move at least one declared step per notch by default.