p5.js addon library

p5.waves

35 wave shapes. One function call.
Pass a number in, get a number back. Use it for anything.

See all 35 waves ↓

Try It

Pick a wave, drag the sliders, see the code update live.

Wave Shift

One flag. The library picks a random wave, holds it, then smoothly morphs into the next one. Different every time you load the page.

Seamless Closing

A ring sampled with shift normally tears its seam open the moment it lands on a new wave - every formula has its own period. The 'closing' pool fixes that: all 19 waves in it share one base period, so a sweep of ring.period times the lobe count closes through every morph. The loop keeps changing shape and never shows a seam.

// These four are plain sketch constants. You pick them. const LOBES = 6; // how many lobes around the ring const SEGS = 3000; // points drawn around the ring const RADIUS = 200; // base radius in pixels const WOBBLE = 70; // wave height in pixels // The sampler auto-shifts through the 'closing' pool. let ring = Waves.createSampler({ shift: true, group: 'closing', amplitude: 1 }); // ring.period comes straight from the library: 62.8319 // for the closing pool. That is why the sweep keeps // closing even as the wave shifts. You never type it. let sweep = ring.period * LOBES; for (let i = 0; i < SEGS; i++) { let frac = i / SEGS; let r = RADIUS + ring.sample(frac * sweep, t) * WOBBLE; vertex(cos(frac * TWO_PI) * r, sin(frac * TWO_PI) * r); }

Not So Random Walker

No angles, no steps - wave output IS the velocity. Fifteen trails in five colors, grouped into a cold pair and a warm pair of shift-samplers. Same-color walkers share a sampler, so they move as a family; the two temperature families transform on different schedules. Rendered on an 8px grid for that old-school bitmap feel.

// Cold pair drives blue + cyan walkers. // Warm pair drives red + yellow + pink. let coldX = Waves.createSampler({ shift: true, group: 'gentle', amplitude: 5, frequency: 0.4, seed: 0 }); let coldY = Waves.createSampler({ shift: true, group: 'gentle', amplitude: 5, frequency: 0.3, seed: 77 }); let warmX = Waves.createSampler({ shift: true, group: 'gentle', amplitude: 5, frequency: 0.4, seed: 311 }); let warmY = Waves.createSampler({ shift: true, group: 'gentle', amplitude: 5, frequency: 0.3, seed: 488 }); // Wave output IS velocity: let xS = isCold ? coldX : warmX; let yS = isCold ? coldY : warmY; wx += xS.sample(t * 1.8 + phase, t); wy += yS.sample(t * 2.1 + phase, t);

3D Terrain

Two independent wave samplers drive X and Z height.

100 Ways to Use p5.waves

Every cell is a unique sketch powered by the library. Waveforms as engines for motion, color, shape, and pattern.

Get Started

Add the script tag. Call the function. Done.

<script src="p5.waves.js"></script> function draw() { for (let x = 0; x < width; x += 3) { let y = Waves.wave(x, { wave: 'mountain peaks', t: millis() / 1000, amplitude: 80 }); point(x, height / 2 + y); } }
Examples → Guide →