You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
83 lines
1.9 KiB
JavaScript
83 lines
1.9 KiB
JavaScript
2 years ago
|
// SARS-CoV-2-Viz
|
||
|
// Animated COVID case count visualization
|
||
|
// Copyright 2022 Edward L. Platt <ed@elplatt.com>
|
||
|
|
||
|
function UI() {
|
||
|
|
||
|
let frames = [];
|
||
|
let currentFrame = 0;
|
||
|
let msPerFrame = 500;
|
||
|
let playing = false;
|
||
|
let onTick = null;
|
||
|
|
||
|
let animate = function () {
|
||
|
if (playing) {
|
||
|
setTimeout(animate, msPerFrame);
|
||
|
}
|
||
|
if (onTick) {
|
||
|
onTick(currentFrame);
|
||
|
}
|
||
|
currentFrame = (currentFrame + 7) % frames.length;
|
||
|
};
|
||
|
|
||
|
let node = document.createElement("div");
|
||
|
|
||
|
let controls = document.createElement("div");
|
||
|
node.appendChild(controls);
|
||
|
|
||
|
let play = document.createElement("button");
|
||
|
play.innerText = 'play';
|
||
|
play.id = 'play';
|
||
|
controls.appendChild(play);
|
||
|
play.addEventListener(
|
||
|
"click", () => {
|
||
|
if (playing) {
|
||
|
play.innerText = 'play';
|
||
|
playing = false;
|
||
|
} else {
|
||
|
play.innerText = 'pause';
|
||
|
playing = true;
|
||
|
animate();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
let display = document.createElement("div");
|
||
|
display.id = "display";
|
||
|
let mainDisplay = document.createElement("div");
|
||
|
mainDisplay.id = "main-display";
|
||
|
let secondaryDisplays = {};
|
||
|
display.appendChild(mainDisplay);
|
||
|
node.appendChild(display);
|
||
|
|
||
|
return {
|
||
|
node: node,
|
||
|
display: (s, id=null) => {
|
||
|
if (id === null) {
|
||
|
mainDisplay.innerText = s;
|
||
|
} else {
|
||
|
secondaryDisplays[id].innerText = s;
|
||
|
}
|
||
|
},
|
||
|
addDisplay: (id) => {
|
||
|
let secondary = document.createElement("div");
|
||
|
secondary.id = `display-${id}`;
|
||
|
display.appendChild(secondary);
|
||
|
secondaryDisplays[id] = secondary;
|
||
|
},
|
||
|
clearDisplays: () => {
|
||
|
mainDisplay.innerText = '';
|
||
|
for (const [id, d] of Object.entries(secondaryDisplays)) {
|
||
|
d.remove();
|
||
|
}
|
||
|
secondaryDisplays = {};
|
||
|
},
|
||
|
onTick: (f) => { onTick = f; },
|
||
|
setFrames: (newFrames, current) => {
|
||
|
frames = newFrames;
|
||
|
currentFrame = current;
|
||
|
},
|
||
|
setMsPerFrame: (newMsPerFrame) => { msPerFrame = newMsPerFrame; }
|
||
|
}
|
||
|
}
|
||
|
|