Skip to content

Instantly share code, notes, and snippets.

@vsapsai
Forked from mbostock/.block
Last active October 23, 2019 22:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vsapsai/10750101 to your computer and use it in GitHub Desktop.
Save vsapsai/10750101 to your computer and use it in GitHub Desktop.
Kyiv Metro digital clock.

Digital clock like in Kyiv Metro, 1970s style. Reference image is provided by Metro Museum.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
background: #111;
position: relative;
}
svg {
position: absolute;
top: 0;
left: 50px;
width: 860px;
height: 500px;
}
#underlay {
-webkit-filter: blur(2px);
-moz-filter: blur(2px);
-ms-filter: blur(2px);
-o-filter: blur(2px);
filter: blur(2px);
}
#underlay path,
#underlay circle {
fill: #111;
stroke: rgb(20, 20, 20);
stroke-opacity: 1;
}
#underlay .lit {
fill: rgb(246, 160, 18);
stroke: rgb(226, 112, 17); /* darker blurred stroke */
}
/* vsapsai: #overlay path, #overlay circle is empty to make visible blurred underlay */
#overlay .lit {
fill: rgb(246, 160, 18);
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var svgUnderlay = d3.select("body").append("svg")
.attr({"width": 270, "height": 50, "viewBox": "0 0 270 50"});
var digitWidth = 5,
digitHeight = 7,
radius = 2,
xStep = 7,
yStep = xStep;
var digitsContainer = svgUnderlay.append("g")
.attr("transform", "translate(17, 0)");
appendDigit(digitsContainer, digitWidth, digitHeight, xStep, yStep, radius)
.attr("transform", "translate(0, 0)");
appendDigit(digitsContainer, digitWidth, digitHeight, xStep, yStep, radius)
.attr("transform", "translate(" + ((digitWidth + 1) * xStep) + ", 0)");
var separatorGroup = digitsContainer.append("g")
.attr("class", "separator")
.attr("transform", "translate(" + ((2 * digitWidth + 1.5) * xStep) + ", 0)");
separatorGroup.append("circle")
.attr({"r": radius, "cx": 0, "cy": yStep * Math.floor(digitHeight / 2)})
.classed("lit", true);
separatorGroup.append("circle")
.attr({"r": radius, "cx": xStep, "cy": yStep * Math.floor(digitHeight / 2)})
.classed("lit", true);
appendDigit(digitsContainer, digitWidth, digitHeight, xStep, yStep, radius)
.attr("transform", "translate(" + ((2 * digitWidth + 4) * xStep) + ", 0)");
appendDigit(digitsContainer, digitWidth, digitHeight, xStep, yStep, radius)
.attr("transform", "translate(" + ((3 * digitWidth + 5) * xStep) + ", 0)");
var secondsGroup = digitsContainer.append("g")
.attr("transform", "translate(" + ((4 * digitWidth + 6.5) * xStep) + ", " +
// vsapsai: it's not a reasonable formula, I tweaked it to look good.
((digitHeight * yStep - 2 * radius - 1) * 0.3) + "), scale(0.7)");
appendDigit(secondsGroup, digitWidth, digitHeight, xStep, yStep, radius)
.attr("transform", "translate(0, 0)");
appendDigit(secondsGroup, digitWidth, digitHeight, xStep, yStep, radius)
.attr("transform", "translate(" + ((digitWidth + 1) * xStep) + ", 0)");
var svgOverlay = d3.select("body").append(function() { return svgUnderlay.node().cloneNode(true); }),
svg = d3.selectAll("svg");
svgUnderlay.attr("id", "underlay");
svgOverlay.attr("id", "overlay");
var digitPattern = [
[0, 1, 1, 1, 0, // 0
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
0, 1, 1, 1, 0],
[0, 0, 1, 0, 0, // 1
0, 1, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0],
[0, 1, 1, 1, 0, // 2
1, 0, 0, 0, 1,
0, 0, 0, 0, 1,
0, 0, 0, 1, 0,
0, 0, 1, 0, 0,
0, 1, 0, 0, 0,
1, 1, 1, 1, 1],
[0, 1, 1, 1, 0, // 3
1, 0, 0, 0, 1,
0, 0, 0, 0, 1,
0, 0, 1, 1, 0,
0, 0, 0, 0, 1,
1, 0, 0, 0, 1,
0, 1, 1, 1, 0],
[0, 0, 0, 1, 0, // 4
0, 0, 1, 0, 0,
0, 1, 0, 0, 1,
1, 0, 0, 0, 1,
1, 1, 1, 1, 1,
0, 0, 0, 0, 1,
0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, // 5
1, 0, 0, 0, 0,
1, 1, 1, 1, 0,
0, 0, 0, 0, 1,
0, 0, 0, 0, 1,
1, 0, 0, 0, 1,
0, 1, 1, 1, 0],
[0, 1, 1, 1, 0, // 6
1, 0, 0, 0, 1,
1, 0, 0, 0, 0,
1, 1, 1, 1, 0,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
0, 1, 1, 1, 0],
[1, 1, 1, 1, 1, // 7
0, 0, 0, 0, 1,
0, 0, 0, 0, 1,
0, 0, 0, 1, 0,
0, 0, 1, 0, 0,
0, 1, 0, 0, 0,
1, 0, 0, 0, 0],
[0, 1, 1, 1, 0, // 8
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
0, 1, 1, 1, 0,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
0, 1, 1, 1, 0],
[0, 1, 1, 1, 0, // 9
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
0, 1, 1, 1, 1,
0, 0, 0, 0, 1,
1, 0, 0, 0, 1,
0, 1, 1, 1, 0]
];
var digit = svg.selectAll(".digit");
(function tick() {
var now = new Date,
hours = now.getHours(),
minutes = now.getMinutes(),
seconds = now.getSeconds();
digit = digit.data([hours / 10 | 0, hours % 10,
minutes / 10 | 0, minutes % 10,
seconds / 10 | 0, ((seconds % 10) / 5 | 0) * 5]);
digit.each(function(d) {
d3.select(this).selectAll("circle")
.classed("lit", function(_, i) { return digitPattern[d][i]; });
});
setTimeout(tick, 1000 - now % 1000);
})();
function appendDigit(parent, width, height, xStep, yStep, radius) {
var digitGroup = parent.append("g")
.attr("class", "digit");
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
digitGroup.append("circle")
.attr({"r": radius, "cx": x * xStep, "cy": y * yStep});
}
}
return digitGroup;
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment