import anime from "https://esm.sh/animejs@3.2.2"; const second = 1000; function gaussianRandom(mean=0, stdev=1) { const u = 1 - Math.random(); // Converting [0,1) to (0,1] const v = Math.random(); const z = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v ); // Transform to the desired mean and standard deviation: return z * stdev + mean; } function* brownian(n){ let x = 0; for(let i = 0; i < n; i ++){ x += gaussianRandom(0, 10); console.log(x); yield x; } } function* pseudoBrownian(n, limit){ let x = 0; for(let i = 0; i < n; i ++){ let delta = gaussianRandom(0, 10); if(Math.abs(x + delta) > limit){ delta = -1 * delta } x += delta; yield x; } } function* keyFrames(duration, framePerSeconds){ const deltaX = 1000 / (duration * framePerSeconds); for(const deltaY of pseudoBrownian(duration * framePerSeconds, 100)){ yield {translateX: `+=${deltaX}`, translateY: deltaY}; } } const duration = 60; const timeline = anime.timeline({ duration: duration * second, autoplay: false, easing: 'linear'}); for(let i = 1; i <= 12; i++){ timeline.add({ targets: `#rect-${i}`, keyframes: Array.from(keyFrames(duration, 30)), }, 0) } document.querySelector('#play').onclick = timeline.play; document.querySelector('#pause').onclick = timeline.pause; document.querySelector('#seek').onclick = function(){ const seekVal = Number.parseFloat(second * document.querySelector('#seek-value').value); timeline.pause(); timeline.seek(seekVal); }