00
classic sine
Use the 35 wave formulas to change a bar's height, a colour or an element's position. The math comes from p5.waves; a shared DOM loop updates your HTML elements.
wave() and createSampler() use the math from p5.waves. vanilla.waves removes the p5 prototype hook and adds a DOM engine.
| Port | Runtime | Draws with |
|---|---|---|
| p5.waves | p5.js | a <canvas> |
| processing.waves | Java / Processing 4 | the Processing surface |
| vanilla.waves | plain DOM, zero deps | any HTML element - bars, dots, text, opacity |
One tag pulls the math plus the DOM engine. Mark an element with data-wv; one shared 30 fps loop animates every marked element and pauses the ones offscreen.
<!-- one tag: math + DOM engine --> <script src="https://cdn.jsdelivr.net/gh/seb-prjcts-be/vanilla.waves@v0.3.1/vanilla.waves.min.js"></script> <div data-wv="eq" data-seed="13"></div>
The sampler returns a number. You can use it for height, position, a character or opacity.
Each bar reads the sampler at a different position. With shift enabled, the meter moves between wave formulas.
// each bar: a sampler value → scaleY v = 0.08 + s.sample(i * 0.55, t) * 0.92; bar.style.transform = 'scaleY(' + v + ')';
One sampler traced across position, drawn as a row of dots. The row is the live waveform, complete with shift and morph.
// dots trace the waveform v = s.sample(i * 0.18, t); dot.style.transform = 'translateY(' + v*38 + 'px)';
A 4×4 grid where each cell picks a glyph from a wave value.
// value → index into a character ramp
idx = floor((v + 1) / 2 * text.length);
cell.textContent = text[idx];
A grid of ink cells whose opacity is a sampler value. Structured like noise, but it breathes and re-forms as the wave shifts.
// each cell: value → opacity
v = (s.sample(c*0.4, t + r*0.5) + 1) / 2;
cell.style.opacity = 0.06 + v * 0.94;
The library includes sines, sawteeth, stepped waves and noise-based shapes. These previews trace them live in SVG.
Skip the engine entirely if you want. A sampler is one value in, one number out - point it at any DOM property in your own loop.
// same numbers as p5.waves - drive anything const s = VanillaWaves.createSampler({ shift: true, range: [-50, 50] }); function tick(now) { el.style.transform = 'translateY(' + s.sample(0, now/1000) + 'px)'; requestAnimationFrame(tick); } requestAnimationFrame(tick);