Would accurate clocks tick in sync all around the world?
Made with d3-component.
forked from curran's block: Clock
Built with blockbuilder.org
license: mit | |
border: no |
Would accurate clocks tick in sync all around the world?
Made with d3-component.
forked from curran's block: Clock
Built with blockbuilder.org
<!DOCTYPE html> | |
<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> |
�PNG | |