109 lines
3.0 KiB
JavaScript
109 lines
3.0 KiB
JavaScript
import anime from "https://esm.sh/animejs@3.2.2";
|
|
import m from "https://esm.sh/mithril@2.2.2"
|
|
import colormap from "https://esm.sh/colormap@2.3.2"
|
|
|
|
|
|
const second = 1000;
|
|
|
|
const canvasWidth = Number.parseFloat(document.querySelector("svg").getAttribute("width"));
|
|
const canvasHeight = Number.parseFloat(document.querySelector("svg").getAttribute("height"));
|
|
|
|
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 = canvasWidth / (duration * framePerSeconds);
|
|
const limit = 0.75 * (canvasHeight / 2);
|
|
for(const deltaY of pseudoBrownian(duration * framePerSeconds, limit)){
|
|
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);
|
|
}
|
|
|
|
|
|
function generatePoints(points, frames){
|
|
const lst = [];
|
|
const colors = colormap({
|
|
colormap: 'viridis',
|
|
nshades: new Set(points.map(p => p.objectId)).size,
|
|
format: 'hex',
|
|
alpha: 1
|
|
});
|
|
for(const point of points){
|
|
if(frames.indexOf(point.frameIndex) !== -1){
|
|
lst.push(m("text", {x: point.y, y: point.x, fill: colors[point.objectId]}, point.objectId));
|
|
}
|
|
}
|
|
return m("g", lst);
|
|
}
|
|
|
|
function getTimeStamp(points, frameId){
|
|
for(const point of points){
|
|
if(point.frameIndex === frameId){
|
|
return `${point.frameTimestamp / 1000} seconds`;
|
|
}
|
|
}
|
|
}
|
|
|
|
const url = "/dodgeball-tracker/outputs/output-lmbn_n_cuhk03_d.json";
|
|
const resp = await fetch(url);
|
|
const points = await resp.json();
|
|
|
|
function range(min, max){
|
|
const ret = [];
|
|
while(min < max){
|
|
ret.push(min);
|
|
min ++;
|
|
}
|
|
return ret
|
|
}
|
|
|
|
m.render(document.getElementById("first"), generatePoints(points.points, range(-10, 400)));
|
|
m.render(document.getElementById("first-ts"), m("span", getTimeStamp(points.points, 80))); |