Examples

Curated motion studies. Built to be copied.

Examples

Purposeful motion, tuned for the real world.

Pulse matrix

Grid-based interference with tempo-driven color.

// Grid interference with tempo-driven color
for (let y = 0; y <= rows; y++) {
  for (let x = 0; x <= columns; x++) {
    const value = Math.sin(x * freq + t) * Math.cos(y * freq + t);
    ctx.arc(x * spacingX, y * spacingY, radius * value, 0, TWO_PI);
  }
}

DNA helix

Two counterphase strands with diagonal drift.

// Counterphase strands with diagonal drift
for (let y = 0; y <= height; y += 6) {
  const xOffset = Math.sin(y * freq + time) * amplitude;
  ctx.moveTo(centerX + xOffset, y);
  ctx.lineTo(centerX - xOffset, y);
}

Fluid column

Vertical flow with volumetric thickness.

// Vertical flow with volumetric thickness
for (let y = 0; y <= height; y += 6) {
  const offset = Math.sin(y * freq + time + col * 0.6) * amp;
  ctx.lineTo(columnX + offset, y);
}

Diagonal rain

Angled strokes with tempo-locked shimmer.

// Angled strokes with tempo-locked shimmer
for (let i = 0; i < count; i++) {
  const drift = Math.sin(time + i * freq) * amplitude;
  ctx.moveTo(baseX + drift, baseY);
  ctx.lineTo(baseX + drift + 24, baseY + 38);
}

Lissajous orbit

Parametric loops synced to time signature.

// Parametric loops synced to time
for (let i = 0; i <= 240; i++) {
  const t = (i / 240) * TWO_PI;
  const x = cx + Math.sin(t * freq + time) * amp;
  const y = cy + Math.sin(t * (freq + 1) + phase) * amp;
}

Waveform terrain

Layered horizons with depth-shifted phases.

// Layered horizons with depth-shifted phases
for (let layer = 0; layer < 8; layer++) {
  for (let x = 0; x <= width; x += 6) {
    const y = baseY + Math.sin(x * freq + phase) * amp;
    ctx.lineTo(x, y);
  }
}

Radial bloom

Outward pulses that peak on the downbeat.

// Outward pulses on the downbeat
for (let r = 18; r < radiusMax; r += 12) {
  const offset = Math.sin(r * freq + time) * pulse;
  ctx.arc(cx, cy, r + offset, 0, TWO_PI);
}

Gradient fill

Area under the wave filled with a linear gradient.

// Area fill with linear gradient
const grad = ctx.createLinearGradient(0, top, 0, height);
for (let x = 0; x <= width; x += 4) {
  ctx.lineTo(x, centerY + Math.sin(x * freq + t) * amp);
}
ctx.fillStyle = grad;
ctx.fill();

Audio visualizer

Simulated volume-driven multi-wave display.

// Volume-driven multi-wave display
waveConfigs.forEach((cfg) => {
  for (let x = 0; x <= width; x += 4) {
    const y = centerY + Math.sin(x * cfg.freq + t * cfg.speed) * amp;
    ctx.lineTo(x, y);
  }
});

Vertical wave

Rotated orientation for liquid-rising effects.

// Rotated orientation for liquid-rising effects
for (let y = 0; y <= height; y += 4) {
  const x = centerX + Math.sin(y * freq + time) * amp;
  ctx.lineTo(x, y);
}

Dash array

Dotted and dashed wave lines via setLineDash.

// Dotted and dashed wave lines
ctx.setLineDash([12, 6]);
for (let x = 0; x <= width; x += 4) {
  const y = centerY + Math.sin(x * freq + time) * amp;
  ctx.lineTo(x, y);
}

Variable width

Pulsing line thickness synchronized to tempo.

// Pulsing line thickness per segment
for (let x = 0; x < width; x += 6) {
  const thickness = 1 + Math.abs(Math.sin(x * 0.01 + t * 2)) * 4;
  ctx.lineWidth = thickness;
  ctx.lineTo(x, centerY + Math.sin(x * freq + t) * amp);
}

Compositing glow

Screen blending for neon glow effects.

// Screen blending for neon glow
ctx.globalCompositeOperation = "screen";
colors.forEach((cfg) => {
  ctx.shadowBlur = 20;
  ctx.lineTo(x, centerY + Math.sin(x * freq + t + cfg.offset) * amp);
});

Zen mode

Ultra-slow motion for maximum smoothness.

// Ultra-slow motion sine
for (let x = 0; x <= width; x += 6) {
  const y = centerY + Math.sin(x * freq + time * 0.15) * amp;
  ctx.lineTo(x, y);
}

Motion lab

High-end motion studies that feel tactile and musical.

String physics

Tap to pluck. Damped amplitude returns to rest.

Tip: click the line to excite it.

// Tap to pluck, damped amplitude returns to rest
canvas.addEventListener("pointerdown", () => { state.amplitude = 100; });
state.amplitude *= 0.95; // decay each frame
const y = centerY + Math.sin(x * 0.02 + phase) * state.amplitude * 0.02;

Audio spectrogram

64 wave forest mapped across bass to treble.

Idle
// 64-band frequency display
analyser.getByteFrequencyData(data);
for (let i = 0; i < 64; i++) {
  const amp = data[i] / 255;
  ctx.moveTo(x, base - amp * height * 0.3);
  ctx.lineTo(x, base + amp * height * 0.3);
}

Lissajous explorer

Orbit knots with adjustable a:b ratios.

// Orbit knots with adjustable a:b ratios
for (let i = 0; i <= 320; i++) {
  const t = (i / 320) * TWO_PI;
  const x = cx + ampX * Math.sin(a * t + delta + time);
  const y = cy + ampY * Math.sin(b * t + time);
}

Feedback loops

Slow modulator controls a fast carrier.

// Slow modulator controls a fast carrier
const mod = Math.sin(time * 0.8);
for (let x = 0; x <= width; x += 4) {
  const carrier = Math.sin(x * carrierFreq + time * 1.6);
  const y = centerY + carrier * baseAmp * mod;
}

Lab presets

Curated scenes you can drop into a hero section.

The Ocean

Horizontal layering with slow tides.

// Horizontal layering with slow tides
// Uses drawWaveformTerrain with 8 depth layers

The Helix

Vertical strands with parallax depth.

// Vertical strands with parallax depth
// Uses drawDNAHelix with counterphase strands

The Pulse

BPM-reactive ripples with color sync.

// BPM-reactive ripples with color sync
// Uses drawRadialBloom with downbeat emphasis

The Orbit

Lissajous curves with orbital drift.

// Lissajous curves with orbital drift
// Uses drawLissajousOrbit with phase shift

Advanced modes

Experimental sketches built on sine-driven motion.

Interference grid

Two angled lattices creating moire shimmer.

// Two angled lattices creating shimmer
const drawGrid = (rotation) => {
  ctx.rotate(rotation);
  for (let x = -max; x <= width + max; x += spacing) {
    ctx.moveTo(x, -max);
    ctx.lineTo(x, height + max);
  }
};

Kinetic typography

Letterforms that breathe with the beat.

// Letterforms that breathe with the beat
"SINE WAVE".split("").forEach((char, i) => {
  const wave = Math.sin(time + i * freq) * amplitude;
  ctx.fillText(char, cx + i * 18, cy + wave);
});

Damped sine

Organic motion with exponential decay.

// Exponential decay envelope
const envelope = Math.exp(-3.2 * progress);
for (let x = 0; x <= width; x += 4) {
  const y = centerY + Math.sin(x * freq + time) * amp * envelope;
  ctx.lineTo(x, y);
}

Recursive sine

Nested oscillators for organic drift.

// Nested oscillators for organic drift
for (let x = 0; x <= width; x += 4) {
  const nested = Math.sin(time + x * baseFreq * 0.4) * 0.6 + 1;
  const y = centerY + Math.sin(x * (freq + mod * nested) + time) * amp;
  ctx.lineTo(x, y);
}