Skip to content

Instantly share code, notes, and snippets.

@Kcnarf
Last active October 23, 2019 22:26
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 Kcnarf/19ac3bbfd6569140b8ad73e723a8443d to your computer and use it in GitHub Desktop.
Save Kcnarf/19ac3bbfd6569140b8ad73e723a8443d to your computer and use it in GitHub Desktop.
Braille Clock
license: gpl-3.0
height: 150
border: no
<!DOCTYPE html>
<meta charset="utf-8">
<style>
#container {
display: flex;
flex-direction: column;
align-items: center;
}
#background {
fill: url("#linear-gradient");
filter: url(#virtual-light);
}
.cell {
fill: url("#radial-gradient");
fill-opacity: 1;
stroke: grey;
stroke-width: 0.2;
}
.unlit {
fill-opacity: 0;
}
</style>
<div id="container">
<svg>
<defs>
<linearGradient id="linear-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="25%" stop-color="#eee"></stop>
<stop offset="75%" stop-color="silver"></stop>
</linearGradient>
<radialGradient id="radial-gradient" cx="40%" cy="40%" r="35%">
<stop offset="25%" stop-color="white"></stop>
<stop offset="75%" stop-color="silver"></stop>
</radialGradient>
<filter id="virtual-light" filterUnits="objectBoundingBox"
x="-0.1" y="-0.1" width="1.2" height="1.2">
<feGaussianBlur in="SourceAlpha" stdDeviation="1" result="alpha_blur"/>
<feSpecularLighting in="alpha_blur" surfaceScale="20" specularConstant="1"
specularExponent="5" lighting-color="white" result="spec_light">
<fePointLight x="-400" y="-400" z="250"/>
</feSpecularLighting>
<feComposite in="SourceGraphic" in2="spec_light" operator="out"/>
</filter>
</defs>
<path id="background"/>
<g transform="translate(20,20)">
</g>
</svg>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var digitHeight = 80,
digitWidth = 80,
interDigitWidth = 20,
numberWidth = digitWidth*2+interDigitWidth;
interNumberWidth = 80,
cellRadius = 10,
cornerRadius = cellRadius+interDigitWidth,
width = 3*numberWidth + 2*interNumberWidth + 2*interDigitWidth,
height = digitHeight + 2*interDigitWidth;
d3.select("svg").attr("width", width).attr("height", height);
d3.select("#background")
.attr("width", width)
.attr("height", height)
.attr("d","M"+[0,cornerRadius]+
"a"+[cornerRadius, cornerRadius, 0, 0, 1, cornerRadius, -cornerRadius]+
"h"+(width-2*cornerRadius)+
"a"+[cornerRadius, cornerRadius, 0, 0, 1, cornerRadius, cornerRadius]+
"v"+(height-2*cornerRadius)+
"a"+[cornerRadius, cornerRadius, 0, 0, 1, -cornerRadius, cornerRadius]+
"h"+(-(width-2*cornerRadius))+
"a"+[cornerRadius, cornerRadius, 0, 0, 1, -cornerRadius, -cornerRadius]+
"z");
svg = d3.select("svg g");
//begin: build digits and Braille cells
var newNumber, newnumberDx,
newDigit, newDigitDx,
newCell, newCellDx, newCellDy;
d3.range(3).forEach(function(number){
newNumberDx = number*(numberWidth+interNumberWidth);
d3.range(2).forEach(function(digit){
newDigitDx = newNumberDx+digit*(digitWidth+interDigitWidth);
newDigit = svg.append("g")
.classed("digit", true)
.attr("transform", "translate("+newDigitDx+",0)");
d3.range(2).forEach(function(hCellIndex){
newCellDx = (hCellIndex===0)? cellRadius : digitWidth-cellRadius;
d3.range(2).forEach(function(vCellIndex){
newCellDy = (vCellIndex===0)? cellRadius : digitHeight-cellRadius;
newDigit.append("circle")
.classed("cell", true)
.attr("r", cellRadius)
.attr("cx", newCellDx)
.attr("cy", newCellDy);
})
})
})
})
//end: build digits and Braille cells
var digit = svg.selectAll(".digit"),
separator = svg.selectAll(".separator circle");
var unlitPattern = [
//[0,1,2,3,4,5,6,7,8,9]
[1,0,0,0,0,0,0,0,0,1],
[0,1,0,1,1,1,0,0,0,0],
[0,1,1,0,0,1,0,0,1,0],
[0,1,1,1,0,0,1,0,0,1],
];
var translatePattern = [
//[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[-1, 0, 0, 0, 0, 0, 0, 0, 0,-1],
[ 0, 1, 0, 1, 1, 1, 0, 0, 0, 0],
[ 0,-1,-1, 0, 0,-1, 0, 0,-1, 0],
[ 0, 1, 1, 1, 0, 0, 1, 0, 0, 1],
];
(function tick() {
var now = new Date,
hours = now.getHours(),
minutes = now.getMinutes(),
seconds = now.getSeconds()
updateType = "lit";
digit = digit.data([hours / 10 | 0, hours % 10, minutes / 10 | 0, minutes % 10, seconds / 10 | 0, seconds % 10]);
if (updateType==="lit") {
digit.select("circle:nth-child(1)").classed("unlit", function(d) { return unlitPattern[0][d]; });
digit.select("circle:nth-child(2)").classed("unlit", function(d) { return unlitPattern[1][d]; });
digit.select("circle:nth-child(3)").classed("unlit", function(d) { return unlitPattern[2][d]; });
digit.select("circle:nth-child(4)").classed("unlit", function(d) { return unlitPattern[3][d]; });
} else if (updateType==="translate") {
digit.select("circle:nth-child(1)").transition().attr("transform", function(d) { return "translate(0,"+2*cellRadius*translatePattern[0][d]+")"; });
digit.select("circle:nth-child(2)").transition().attr("transform", function(d) { return "translate(0,"+2*cellRadius*translatePattern[1][d]+")"; });
digit.select("circle:nth-child(3)").transition().attr("transform", function(d) { return "translate(0,"+2*cellRadius*translatePattern[2][d]+")"; });
digit.select("circle:nth-child(4)").transition().attr("transform", function(d) { return "translate(0,"+2*cellRadius*translatePattern[3][d]+")"; });
}
setTimeout(tick, 1000 - now % 1000);
})();
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment