Public
Edited
Dec 15, 2023
Fork of Polar Clock
Insert cell
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("text-anchor", "middle")
.style("display", "block")
.style("font", "500 14px var(--sans-serif)")

const field = svg.append("g")
.attr("transform", `translate(${width / 2},${height / 2})`)
.selectAll("g")
.data(fields)
.join("g")

field.append("circle")
.attr("fill", "none")
.attr("stroke", "currentColor")
.attr("stroke-width", 1.5)
.attr("r", d => d.radius)

const fieldTick = field.selectAll("g")
.data(d => {
const date = d.interval(new Date(2000, 0, 1))
d.range = d.subinterval.range(date, d.interval.offset(date, 1))
return d.range.map(t => ({time: t, field: d}))
})
.join("g")
.attr("class", "field-tick")
.attr("transform", (d, i) => {
const angle = i / d.field.range.length * 2 * Math.PI - Math.PI / 2
return `translate(${Math.cos(angle) * d.field.radius},${Math.sin(angle) * d.field.radius})`
})

const fieldCircle = fieldTick.append("circle")
.attr("r", dotRadius)
.attr("fill", "white")
.style("color", (d, i) => color(i / d.field.range.length * 2 * Math.PI))
.style("transition", "fill 750ms ease-out");

fieldTick.append("text")
.attr("dy", "0.35em")
.attr("fill", "#222")
.text(d => d.field.format(d.time).slice(0, 2));

const fieldFocus = field.append("circle")
.attr("r", dotRadius)
.attr("fill", "none")
.attr("stroke", "#000")
.attr("stroke-width", 1)
.attr("stroke-opacity", .4)
.attr("cy", d => -d.radius)
.style("transition", "transform 500ms ease");

svg.append("circle") //prevent select field tiks on grag
.attr("transform", `translate(${width / 2},${height / 2})`)
.attr('r', radius).attr('fill-opacity', 0)
const len = d => d.radius * 2 * Math.PI / d.range.length,
timeShiftRing = svg.append("g")
.attr('class', 'time-shift-rings')
.attr("transform", `translate(${width / 2},${height / 2})`)
.selectAll("g")
.data(fields)
.join("g")
.call(drag)
timeShiftRing.append("g")
.attr("transform", d => `rotate(${-90-len(d)/d.radius*180/Math.PI/2+WTF[2]})`)
.append("circle")
.attr("stroke-width", dotRadius * 2 + 2)
.style('stroke-dasharray', d => `${len(d) - 5} 5`)
.attr("r", d => d.radius)

timeShiftRing.append("circle") // hover hot area
.attr("stroke-width", dotRadius * 3 + 3)
.attr("r", d => d.radius)
.style('stroke-opacity', 0)
// timeShiftRing.append("line")
// .attr("stroke", "currentColor")
// .attr('y1', d => -d.radius + dotRadius)

timeShiftRing.append('path')
.attr('fill', 'gray')
.attr("transform", d => `translate(0, ${-d.radius-dotRadius+8}) scale(2)`)
.attr('d', 'M 0 0 L -2 -3 L 2 -3 Z')

const centerControl = svg.append("g")
.attr("transform", `translate(${width / 2},${height / 2})`)

const timeScaleRate = centerControl.append("text")
.attr('transform', `translate(0, -${fields[0].radius / 3})`)
const centerDate = centerControl.append("text")
window.centerAngle = centerControl.append("text")
.attr('transform', `translate(0, ${fields[0].radius / 3})`)
yield update(Math.floor((Date.now() + 1) / 1000) * 1000)
while (true) {
const then = Math.ceil((Date.now() + 1) / 1000) * 1000
yield Promises.when(then, then).then(update)
}

function update(then) {
const formatTime = d3.timeFormat("%d.%m.%Y %H:%M:%S")
timeScaleRate.text('Real time x1')
centerDate.text(formatTime(new Date(then)))
for (const d of fields) {
const start = d.interval(then)
const index = d.subinterval.count(start, then)
d.cycle = (d.cycle || 0) + (index < d.index)
d.index = index
}
fieldCircle.attr("fill", (d, i) => i === d.field.index ? "currentColor" : "white")
fieldFocus.attr("transform", d => `rotate(${(d.index / d.range.length + d.cycle) * 360})`)
return svg.node()
}
}
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

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more