year = {
const clockRadius = 200,
margin = 25,
w = (clockRadius + margin) * 2,
h = (clockRadius + margin) * 2,
hourHandLength = (2 * clockRadius) / 3,
minuteHandLength = clockRadius,
secondHandLength = clockRadius - 12,
secondHandBalance = 30,
secondTickStart = clockRadius,
secondTickLength = -10,
hourTickStart = clockRadius,
hourTickLength = -18,
secondLabelRadius = clockRadius + 16,
secondLabelYOffset = 5,
hourLabelRadius = clockRadius - 40,
hourLabelYOffset = 7,
radians = Math.PI / 180;
const seven = d3
.scaleLinear()
.range([90, -270])
.domain([0, 7]);
const sevenrotate = d3
.scaleLinear()
.range([0, 360])
.domain([0, 7]);
const handData = [
{
type: "second",
value: 0,
length: -secondHandLength,
scale: seven,
balance: secondHandBalance
}
];
function drawClock() {
// create all the clock elements
updateData(); //draw them in the correct starting position
const face = svg
.append("g")
.attr("id", "year-face")
.attr("transform", `translate(${[w / 2, h / 2]})`);
// add marks for seconds
face
.selectAll(".second-tick")
.data(d3.range(0, 7))
.enter()
.append("line")
.attr("class", "second-tick")
.attr("x1", 0)
.attr("x2", 0)
.attr("y1", secondTickStart)
.attr("y2", secondTickStart + secondTickLength)
.attr("transform", d => `rotate(${sevenrotate(d)})`);
// and labels...
face
.selectAll(".second-label")
.data(d3.range(0, 7))
.enter()
.append("text")
.attr("class", "second-label")
.attr("text-anchor", "middle")
.attr("x", d => secondLabelRadius * Math.sin(seven(d) * radians))
.attr(
"y",
d =>
secondLabelRadius * Math.cos(seven(d) * radians) + secondLabelYOffset
)
.text(d => ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"][d]);
const hands = face.append("g").attr("id", "year-hands-final");
hands
.selectAll("line")
.data(handData)
.enter()
.append("line")
.attr("class", d => d.type + "-hand")
.attr("x1", 0)
.attr("y1", d => d.balance || 0)
.attr("x2", 0)
.attr("y2", d => d.length)
.attr("transform", d => `rotate(${d.scale(d.value)})`);
face
.append("g")
.attr("id", "face-overlay")
.append("circle")
.attr("class", "hands-cover")
.attr("x", 0)
.attr("y", 0)
.attr("r", clockRadius / 20);
}
function moveHands() {
const sel = d3
.select("#year-hands-final")
.selectAll("line")
.data(handData)
.transition();
sel.attr("transform", d => `sevenrotate(${d.scale(d.value)})`);
}
function updateData() {
const t = new Date();
handData[0].value = (t.getDay() + 6) % 7 + (t.getHours() + (t.getMinutes() + (t.getSeconds() + t.getMilliseconds() / 1000 ) / 60) / 60) / 24;
}
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, w, h])
.style("max-width", "500px")
.attr("id", "clock");
drawClock();
// Animation
const interval = setInterval(
() => {
updateData();
moveHands();
},
1000
);
invalidation.then(() => clearInterval(interval));
return svg.node();
}