Would accurate clocks tick in sync all around the world?
Made with d3-component.
forked from curran's block: Clock
Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/d3@4"></script>
<script src="https://unpkg.com/d3-component@3"></script>
<style>
body {
margin: 0px;
}
.labeled-clock {
display: inline-block;
margin: 0px 0px 11px 24px;
}
.clock-label {
margin: -3px 0px 0px 0px;
text-align: center;
font-size: 1.8em;
}
</style>
</head>
<body>
<script>
var clock = (function (){
var timerLocal = d3.local();
return d3.component("svg")
.create(function (selection, d){
var width = d.width,
height = d.height,
side = Math.min(width, height),
outerCircleStrokeWidth = side * d.outerCircleThickness,
centralCircleRadius = side * d.centralCircleSize,
numbersRadius = side/2 * d.numbersRadius,
numbersFontSize = side/10 * d.numbersSize + "px",
numbersXOffset = side * d.numbersXOffset,
numbersYOffset = side * d.numbersYOffset,
ampmFontSize = side/10 * d.ampmSize + "px",
second = 1000,
minute = second * 60,
hour = minute * 60,
day = hour * 24,
halfDay = hour * 12,
// TODO add actual check for whether we're in daylight savings time.
daylightSavingsOffset = d.daylightSavings ? 1 : 0,
timeZoneOffset = d.timeZoneOffset + daylightSavingsOffset,
midnight = d3.utcDay(new Date()) - timeZoneOffset * hour,
grays = d3.interpolateLab("black", "lightgray"),
axle = selection.append("g")
.attr("transform", "translate(" + [width/2, height/2] + ")"),
outerCircle = axle.append("circle")
.attr("r", side / 2 - outerCircleStrokeWidth)
.attr("fill", d.fillColor)
.attr("stroke", "black")
.attr("stroke-width", outerCircleStrokeWidth),
ampm = axle.append("text")
.attr("text-anchor", "middle")
.attr("alignment-baseline", "middle")
.attr("font-size", ampmFontSize)
.attr("font-family", d.ampmFontFamily)
.attr("fill", d.ampmColor)
.attr("y", side * d.ampmYOffset);
// SVG dimensions.
selection
.attr("width", width)
.attr("height", height);
// Numbers.
axle.selectAll(".number").data(d3.range(12).reverse())
.enter().append("text")
.attr("class", "number")
.attr("x", function (d, i){
return -Math.sin(i/6 * Math.PI) * numbersRadius + numbersXOffset;
})
.attr("y", function (d, i){
return -Math.cos(i/6 * Math.PI) * numbersRadius + numbersYOffset;
})
.attr("text-anchor", "middle")
.attr("alignment-baseline", "middle")
.attr("font-size", numbersFontSize)
.attr("font-family", d.numbersFontFamily)
.text(function (d){ return d + 1; });
// Ticks.
var tickMinorRadius = side / 2 * d.tickMinorRadius,
tickMajorRadius = side / 2 * d.tickMajorRadius,
tickRingRadius = side / 2 * d.tickRingRadius;
axle.selectAll(".tick").data(d3.range(60))
.enter().append("circle")
.attr("class", "tick")
.attr("cx", function (d, i){
return Math.sin(i/30 * Math.PI) * tickRingRadius;
})
.attr("cy", function (d, i){
return Math.cos(i/30 * Math.PI) * tickRingRadius;
})
.attr("r", function (d, i){
return i % 5 ? tickMinorRadius : tickMajorRadius;
})
.attr("fill", "black")
function hand(handLength, handWidth, color){
var spindle = axle.append("g");
spindle.append("line")
.attr("x2", side / 2 * handLength)
.attr("stroke", color || "black")
.attr("stroke-width", side * handWidth)
.attr("stroke-linecap","round");
return spindle;
}
var hourHand = hand(d.hourHandLength, d.hourHandWidth),
minuteHand = hand(d.minuteHandLength, d.minuteHandWidth),
secondHand = hand(d.secondHandLength, d.secondHandWidth),
centralCircle = axle.append("circle")
.attr("r", centralCircleRadius),
millisecondHand = hand(d.msHandLength, d.msHandWidth, "white");
function angle(ms, timespan){
return (ms / timespan % 1) * 360 - 90;
}
timerLocal.set(selection.node(), d3.timer(function (){
var ms = Date.now() - midnight;
hourHand.attr("transform", "rotate(" + angle(ms, halfDay) + ")");
minuteHand.attr("transform", "rotate(" + angle(ms, hour) + ")");
secondHand.attr("transform", "rotate(" + angle(ms, minute) + ")");
millisecondHand.attr("transform", "rotate(" + angle(ms, second) + ")");
centralCircle.attr("fill", grays(angle(ms, second) / 360));
ampm.text((ms / day % 1) < 0.5 ? "AM" : "PM");
}));
})
.destroy(function (selection){
timerLocal.get(selection.node()).stop();
});
}());
var label = d3.component("div", "clock-label")
.render(function (selection, d){ selection.text(d); });
var labeledClock = d3.component("div", "labeled-clock")
.render(function (selection, d){
selection
.call(clock, d)
.call(label, d.label);
});
var clockStyle = {
width: 210,
height: 210,
outerCircleThickness: 0.01,
centralCircleSize: 0.04,
hourHandLength: 0.56,
hourHandWidth: 0.0348,
minuteHandLength: 0.65,
minuteHandWidth: 0.015,
secondHandLength: 0.9,
secondHandWidth: 0.005,
msHandLength: 0.08,
msHandWidth: 0.005,
numbersRadius: 0.84,
numbersSize: 1.2144,
numbersFontFamily: "serif",
numbersXOffset: 0.000,
numbersYOffset: 0.015,
fillColor: "#fffef9",
ampmSize: 2.3,
ampmFontFamily: "sans-serif",
ampmColor: "#c5c3b8",
ampmYOffset: 0.18,
tickRingRadius: 0.68,
tickMinorRadius: 0.01,
tickMajorRadius: 0.02
}
labeledClock(document.body, [
{ label: "San Francisco", timeZoneOffset: -8, daylightSavings: true },
{ label: "New York", timeZoneOffset: -5, daylightSavings: true },
{ label: "Sao Paulo", timeZoneOffset: -3 },
{ label: "London", timeZoneOffset: 0 },
{ label: "Dubai", timeZoneOffset: 4 },
{ label: "Mumbai", timeZoneOffset: 5.5 },
{ label: "Beijing", timeZoneOffset: 8 },
{ label: "Sydney", timeZoneOffset: 11 }
], clockStyle);
</script>
</body>
https://unpkg.com/d3@4
https://unpkg.com/d3-component@3