Chladni sand patterns: millions of grains gather on the nodal lines of a vibrating plate and re-form from mode to mode like sound made visible; the pointer drives the plate and a strike scatters the sand.

  • shader
  • webgl
  • chladni
  • sand
  • sound
  • background
  • hero
  • interactive
Preset

Installation

Pro — coming soon

The source and installation instructions for this item ship with Kagadmodyaa Pro.

Usage

Use it like any other component. Choose a theme with preset; any prop you pass as well overrides the preset.

import { useRef } from 'react'
import { Cymatics, type CymaticsHandle } from '@/components/effects/cymatics/cymatics'

export function Hero() {
  const plate = useRef<CymaticsHandle>(null)
  return (
    <section className="relative h-[640px] overflow-hidden">
      {/* fills its parent; autoplay cycles patterns, mode={[5, 3]} pins one */}
      <Cymatics ref={plate} preset="Obsidian" shape="square" className="absolute inset-0" />
      <div className="relative z-10 p-12">
        <h1>Sound, made visible.</h1>
        <button onClick={() => plate.current?.strike()}>Strike the plate</button>
        <button onClick={() => plate.current?.setMode(4, 7)}>Mode 4:7</button>
      </div>
    </section>
  )
}

// Presets: Brass, Obsidian, Paper (made for light pages), Cyan Resonance, Rose Quartz.
// The stage above is <CymaticsShowcase />, also exported: the plate with the readout and a Strike button.
<Cymatics preset="Obsidian" autoplay={true} />

Presets

  • Brass
  • Obsidian
  • Paper
  • Cyan Resonance
  • Rose Quartz

Props

NameTypeDefaultDescription
preset'Brass' | 'Obsidian' | 'Paper' | 'Cyan Resonance' | 'Rose Quartz'none (the defaults below)A named theme. Any prop you pass as well overrides the preset’s value.
autoplaybooleantrueVisit a tour of patterns on its own: each one dissolves into the next. Off pins the pattern at the mode n and m below.
modeNnumber5Mode number along x. On a round plate it is the angular order plus one. Moving it goes to that pattern at once, with autoplay on or off. Range 1 to 12.
modeMnumber3Mode number along y. On a round plate it is the radial index. The pitch rises with n squared plus m squared. Range 1 to 12.
morphSpeednumber1How quickly one pattern gives way to the next, and how long each is held. Range 0.1 to 2.5.
shape'fill' | 'square' | 'round''fill'square and round show a plate lying on a table; fill makes the plate the whole box.
plateSizenumber0.86Width of a square or round plate as a fraction of the shorter side of the box. Range 0.5 to 1.
surface'brushed' | 'glass' | 'paper''brushed'The material of the plate: brushed metal, dark glass or matte paper.
lightAnglenumber128Where the light comes from, in degrees: 0 is the right, 90 the top. Range 0 to 360.
grainSizenumber2.3Size of one grain in CSS pixels. Range 1 to 4.5.
densitynumber1How much sand is on the plate. Range 0.2 to 1.6.
sharpnessnumber0.6How tightly the sand hugs the nodal lines. Low values leave wide soft drifts. Range 0 to 1.
shimmernumber0.5The faint ripples that shimmer on the antinodes, where the plate moves most. Range 0 to 1.
glownumber0.12Soft light around the sand lines. Made for dark plates. Range 0 to 1.5.
sandColorstring'#e9b858'Colour of the sand. A hex colour.
plateColorstring'#241608'Colour of the plate. A light colour gives the paper look. A hex colour.
highlightColorstring'#fff0c2'Colour of the glints on the sand and the sheen on the plate. A hex colour.
pointerInfluencenumber0.6How strongly the pointer drives the plate around itself and shifts the mode mix. 0 ignores the pointer. Range 0 to 1.
strikeStrengthnumber1How violently a strike scatters the sand. Range 0 to 1.5.
strikeOnClickbooleantrueA click or tap strikes the plate. Call strike() on a ref to do it from code.
grainnumber0.3Amount of film grain over the picture. Range 0 to 1.
readoutbooleantrueShow the frequency and mode as real text on the stage.
classNamestring—Extra class on the root element. The effect fills its parent: give the parent a height.
styleCSSProperties—Inline style on the root element.

Behaviour

  • A plate vibrates in one mode after another. Grain density follows the standing wave: sand migrates to the nodal lines where the plate stands still and leaves the antinodes bare, where a faint ripple shimmers instead. With autoplay on, each pattern dissolves into the next and re-forms; pin one with the mode prop or the mode n and m controls.
  • Move the pointer over the plate: it is the driver. Sand near it re-sorts into ripples around the cursor, and moving across the plate shifts the mix between the two mirrored halves of the mode. Set pointerInfluence to 0 to ignore the pointer.
  • A click or tap strikes the plate: a ring of vibration races outward, the sand scatters and blurs out, and it settles into the next pattern (the same one when autoplay is off). Call strike(strength, [x, y]) on a ref, or setMode(n, m) to move to a pattern; strikeOnClick turns the click off.
  • The plate can be a whole-box surface (fill), or a square or round plate lying on a table. The Paper preset is graphite grains on warm paper, made for light pages.
  • It pauses off screen and in a background tab, lowers its resolution automatically if frames run slow, and draws one still pattern under prefers-reduced-motion. Without WebGL you see an SVG poster of the same pattern. The frequency readout is real text.

See all effects