Skip to content

Instantly share code, notes, and snippets.

@curran
Last active March 25, 2017 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save curran/28047fcfeb11cc0c66d10e7f30e1fe22 to your computer and use it in GitHub Desktop.
Save curran/28047fcfeb11cc0c66d10e7f30e1fe22 to your computer and use it in GitHub Desktop.
Clock
license: mit

A clock, constructed using nested components with d3-component.

Since we're not confined to physical limitations, why not have a "millisecond hand"?!

This is an optimized and refactored version of the first-pass implementation: Poorly Performing 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>
</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,
midnight = d3.timeDay(new Date()).getTime(),
second = 1000,
minute = second * 60,
hour = minute * 60,
day = hour * 12;
// Update SVG dimensions.
selection
.attr("width", width)
.attr("height", height);
// Outer circle.
selection.append("circle")
.attr("cx", width / 2)
.attr("cy", height / 2)
.attr("r", side / 2 - outerCircleStrokeWidth)
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", outerCircleStrokeWidth);
// Central circle.
selection.append("circle")
.attr("cx", width / 2)
.attr("cy", height / 2)
.attr("r", centralCircleRadius);
function hand(handLength, handWidth, color){
var spindle = selection.append("g")
.attr("transform", "translate(" + width/2 + "," + height/2 + ")")
.append("g");
spindle.append("line")
.attr("x2", side / 2 * handLength)
.attr("stroke", color || "black")
.attr("stroke-width", side * handWidth);
return spindle;
}
var hourHand = hand(d.hourHandLength, d.hourHandWidth),
minuteHand = hand(d.minuteHandLength, d.minuteHandWidth),
secondHand = hand(d.secondHandLength, d.secondHandWidth),
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, day) + ")");
minuteHand.attr("transform", "rotate(" + angle(ms, hour) + ")");
secondHand.attr("transform", "rotate(" + angle(ms, minute) + ")");
millisecondHand.attr("transform", "rotate(" + angle(ms, second) + ")");
}));
})
.destroy(function (selection){
timerLocal.get(selection.node()).stop();
});
}());
d3.select("body")
.call(clock, {
width: 960,
height: 500,
outerCircleThickness: 0.01,
centralCircleSize: 0.04,
hourHandLength: 0.7,
hourHandWidth: 0.03,
minuteHandLength: 0.85,
minuteHandWidth: 0.015,
secondHandLength: 0.9,
secondHandWidth: 0.005,
msHandLength: 0.08,
msHandWidth: 0.004
});
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment