Published
Edited
Sep 10, 2020
2 forks
95 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
// 01:15 expressed in hours
const hours = 1.25;

// Create SVG that can fit a clock with the configured radius
const size = 2 * settings.radius;
const svgNode = DOM.svg(size, size);

// Add the clock and set the time
d3.select(svgNode)
.call(addClock)
.datum(hours)
.call(updateClock);

return svgNode;
}
Insert cell
Insert cell
Insert cell
{
const clocks = Object.values(hoursByOrientation);

// Create SVG that can fit all the clocks
const size = 2 * settings.radius;
const svgNode = DOM.svg(clocks.length * size, size);

// Add the clocks and set their times
d3.select(svgNode)
.selectAll("g")
.data(clocks)
.join("g")
.style("transform", (d, i) => `translate(${i * size}px, 0px)`)
.call(addClock)
.call(updateClock);

return svgNode;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
// Prepare SVG with width 1/5 of the viewport
const svgNode = svg`<svg width="${width / 5}"/>`;
// Draw the sprite for the digit "9"
updateSvg(svgNode, spriteGrids[9]);

return svgNode;
}
Insert cell
Insert cell
{
// Create SVG that can fit a single clock as before and yield it
const size = 2 * settings.radius;
const svgNode = DOM.svg(5 * size, size);
yield svgNode;

// Add a clock
d3.select(svgNode).call(addClock);

const counter = d3
.select(svgNode)
.append("text")
.style("font-size", `${settings.radius / 2}px`)
.style("transform", "translate(72px, 36px)");

// Set hours to transition between (01:15 => 10:30)
const hoursFrom = 1.25;
const hoursTo = 10.5;

const interval = 4000;
const delayBeforeRestart = 1000;

// Update the SVG 60 times per second
const framesPerSecond = 60;

// Start an "infinite" loop that is stopped when the cell is re-evaluated
let running = true;
invalidation.then(() => (running = false));

while (running) {
const intervalWithDelay = interval + delayBeforeRestart;
let normalizedTime = (new Date().getTime() % intervalWithDelay) / interval;
normalizedTime = Math.min(1, normalizedTime);
const hours = interpolateHours(hoursFrom, hoursTo, normalizedTime);
counter.text(`Normalized time: ${normalizedTime.toFixed(2)}`);

// Add the clocks and set their times
d3.select(svgNode)
.datum(hours)
.call(updateClock);

// Wait until it is time for the next frame
await Promises.tick(1000 / framesPerSecond);
}
}
Insert cell
Insert cell
{
// Prepare SVG with width 1/5 of the viewport
const svgNode = svg`<svg width="${width / 5}"/>`;
yield svgNode;

// Change to the next digit every 4000 milliseconds
const interval = 4000;

// Update the SVG 60 times per second
const framesPerSecond = 60;

// Start an "infinite" loop that is stopped when the cell is re-evaluated
let running = true;
invalidation.then(() => (running = false));

while (running) {
// Calculate current and next digit and normalized time
const time = new Date().getTime();
const digit = Math.floor(time / interval) % 10;
const nextDigit = (digit + 1) % 10;
const normalizedTime = (time % interval) / interval;

// Update with interpolation between current and next digit
updateSvg(
svgNode,
interpolateGrid(
spriteGrids[digit],
spriteGrids[nextDigit],
normalizedTime
)
);

// Wait until it is time for the next frame
await Promises.tick(1000 / framesPerSecond);
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more