Esc

Try “tilt”, “reveal”, “drag”, or “reduced motion”.

Extras

Audio

Turn an audio or video element, a microphone, or any Web Audio node into signals that drive motion.

The audio module measures loudness in frequency ranges and exposes each one as a signal. Bind signals to any property.

import { kinesis } from "@amineyarman/kinesis"
import { createAudio } from "@amineyarman/kinesis/audio"

const audio = createAudio(document.querySelector("audio"))

kinesis(".speaker__cone").bind({
  scale: audio.bass.map([0.78, 0.95], [1, 1.3]),
})
Press playEdit
.speaker-scene {
  display: grid;
  gap: 18px;
  place-items: center;
  align-content: center;
  height: 100%;
}

.speaker {
  display: grid;
  place-items: center;
  width: 150px;
  height: 190px;
  border-radius: 22px;
  background: #0c1324;
}

.speaker__cone {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: radial-gradient(circle, #5b8cff 0 18%, #1b2744 20% 55%, #2c3a60 58%);
}

Sources

createAudio() accepts:

  • an <audio> or <video> element, which keeps playing through your speakers
  • a MediaStream, for example from getUserMedia({ audio: true })
  • any Web Audio AudioNode

Signals

SignalRange
volumeoverall loudness
bass20 to 250 Hz
mid250 Hz to 2 kHz
treble2 to 16 kHz
band(from, to)any range in Hz

Values go from 0 to 1 on a decibel scale, like the meters on a mixing desk. A loud band often sits between 0.7 and 1, and the useful range depends on the track. Log a band while it plays, then map the range you see:

audio.bass.subscribe((level) => console.log(level.toFixed(2)))

kinesis(".cone").bind({ scale: audio.bass.map([0.78, 0.95], [1, 1.3]) })

Add .spring() for smoother motion.

Autoplay

Browsers keep audio silent until the visitor interacts with the page. With a media element, Kinesis resumes the audio context when playback starts. If you start sound yourself, call audio.resume() from a click handler.

Options and cleanup

const audio = createAudio(element, {
  fftSize: 1024,      // analyser resolution
  smoothing: 0.75,    // 0 reacts instantly, 1 never changes
})

audio.destroy()       // disconnect the analyser

Analysis runs only while something reads the signals and the media plays. A paused track costs nothing.

Edit this page on GitHub