Cymatics
NewProChladni 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
BrassObsidianPaperCyan ResonanceRose Quartz
Props
| Name | Type | Default | Description |
|---|---|---|---|
| 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. |
| autoplay | boolean | true | Visit a tour of patterns on its own: each one dissolves into the next. Off pins the pattern at the mode n and m below. |
| modeN | number | 5 | Mode 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. |
| modeM | number | 3 | Mode 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. |
| morphSpeed | number | 1 | How 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. |
| plateSize | number | 0.86 | Width 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. |
| lightAngle | number | 128 | Where the light comes from, in degrees: 0 is the right, 90 the top. Range 0 to 360. |
| grainSize | number | 2.3 | Size of one grain in CSS pixels. Range 1 to 4.5. |
| density | number | 1 | How much sand is on the plate. Range 0.2 to 1.6. |
| sharpness | number | 0.6 | How tightly the sand hugs the nodal lines. Low values leave wide soft drifts. Range 0 to 1. |
| shimmer | number | 0.5 | The faint ripples that shimmer on the antinodes, where the plate moves most. Range 0 to 1. |
| glow | number | 0.12 | Soft light around the sand lines. Made for dark plates. Range 0 to 1.5. |
| sandColor | string | '#e9b858' | Colour of the sand. A hex colour. |
| plateColor | string | '#241608' | Colour of the plate. A light colour gives the paper look. A hex colour. |
| highlightColor | string | '#fff0c2' | Colour of the glints on the sand and the sheen on the plate. A hex colour. |
| pointerInfluence | number | 0.6 | How strongly the pointer drives the plate around itself and shifts the mode mix. 0 ignores the pointer. Range 0 to 1. |
| strikeStrength | number | 1 | How violently a strike scatters the sand. Range 0 to 1.5. |
| strikeOnClick | boolean | true | A click or tap strikes the plate. Call strike() on a ref to do it from code. |
| grain | number | 0.3 | Amount of film grain over the picture. Range 0 to 1. |
| readout | boolean | true | Show the frequency and mode as real text on the stage. |
| className | string | — | Extra class on the root element. The effect fills its parent: give the parent a height. |
| style | CSSProperties | — | 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.