A pulse on the beat
A disc swells on each beat, and a ring of bars around it ripples and grows taller.
beat(t, beats) reads a beat file, an object whose beats array holds { time, strength }, or that array itself, and returns a value from 0 to 1.
The value jumps to each beat's strength and decays from there, with a time constant of 0.2 s unless { decay } is passed.
<div id="stage" data-composition-id="pulse" data-start="0" data-duration="13" data-width="1280" data-height="720" data-fps="30">
<div class="layer" data-component="pulse" data-start="0" data-duration="13">
<div style="position: absolute; left: 50%; top: 50%; width: 0; height: 0" data-list="bars" data-key="key">
<template><i style="position: absolute; left: -4px; top: -4px; width: 8px; background: #c9b8ff; transform-origin: 50% 0" data-bind-style="style"></i></template>
</div>
<div style="position: absolute; left: 50%; top: 50%; width: 180px; height: 180px; margin: -90px 0 0 -90px; border-radius: 50%; background: #9d7bff" data-bind-style="disc"></div>
</div>
</div>
const { scene, beat, noise, styleAt } = wildflower.kinetic;
wildflower.query('beats', { from: 'data/beats.json', select: (file) => file.beats });
const BARS = 36;
scene('pulse', {
waitFor: ['beats'],
computed: {
pulse() { return beat(this.time, wildflower.getQuery('beats').rows); },
disc() { return styleAt(this.time, { scale: 1 + 0.14 * this.pulse }); },
bars() {
const out = [];
for (let i = 0; i < BARS; i++) {
const n = 0.5 + 0.5 * noise(i * 0.61 + this.time * 1.7, 11);
const h = 18 + 70 * n * (0.35 + 0.65 * this.pulse);
out.push({ key: i, style: { height: h.toFixed(1) + 'px', transform: 'rotate(' + (360 / BARS) * i + 'deg) translateY(112px)' } });
}
return out;
},
},
});
html, body { margin: 0; background: #0a0b10; }
#stage { position: relative; overflow: hidden; background: #0b0f1a; }
.layer { position: absolute; inset: 0; }
[data-composition-id]:not([data-kinetic-ready]) { visibility: hidden; }
A pulse on the beat
Multiplying a scale by 1 + 0.14 * pulse swells an element on each beat.
The ring's bars take their heights from noise() at an offset of each bar's own, scaled by the pulse.
The Captions on a Beat demo pulses a disc and a ring of bars this way.