signals
by phloe
HTML
<div id="timeline"></div>
<button id="control">play/pause</button>
CSS
#timeline {
display: flex;
flex-flow: row nowrap;
gap: 2px;
align-items: end;
height: 200px;
background-color: #EEE;
}
#timeline > * {
width: 2px;
background-color: red;
flex: 0 0 auto;
}
JavaScript
const samples = 10000;
for (let i = 0; i < samples; i++) {
timeline.appendChild(document.createElement("div"));
}
let values = [];
function update () {
values.forEach((value, i) => {
timeline.childNodes[i].style.height = (value * 100) + "%";
});
}
const generators = {
sine(time) {
return (Math.cos(time * Math.PI * 2) + 1) / 2;
},
triangle(time) {
return (time <= 0.5 ? time : (0.5 - (time - 0.5))) * 2;
},
sawtooth(time) {
return time;
},
square(time) {
return time < 0.5 ? 0 : 1;
}
};
const transitions = {
// no easing, no acceleration
linear: t => t,
// accelerating from zero velocity
easeInQuad: t => t*t,
// decelerating to zero velocity
easeOutQuad: t => t*(2-t),
// acceleration until halfway, then deceleration
easeInOutQuad: t => t<.5 ? 2*t*t : -1+(4-2*t)*t,
// accelerating from zero velocity
easeInCubic: t => t*t*t,
// decelerating to zero velocity
easeOutCubic: t => (--t)*t*t+1,
// acceleration until halfway, then deceleration
easeInOutCubic: t => t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1,
// accelerating from zero velocity
easeInQuart: t => t*t*t*t,
// decelerating to zero velocity
easeOutQuart: t => 1-(--t)*t*t*t,
// acceleration until halfway, then deceleration
easeInOutQuart: t => t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t,
// accelerating from zero velocity
easeInQuint: t => t*t*t*t*t,
// decelerating to zero velocity
easeOutQuint: t => 1+(--t)*t*t*t*t,
// acceleration until halfway, then deceleration
easeInOutQuint: t => t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t
};
const duration = 1000;
const freq = 10000;
const amp = 1;
for (let i = 0; i < samples; i++) {
values.push(generators.sine((i % freq) / freq) * amp * transitions.linear(1 - i / samples));
i++;
}
update();
let playing;
let frame;
let start;
function play () {
if (!start) {
start = Date.now();
}
let elapsed = Date.now() - start;
timeline.firstChild.style.height = (values[elapsed % samples] *...