7-segment SVG
by PhilQ
HTML
<svg id="lcd"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<defs>
<filter
id="dropshadow"
filterUnits="userSpaceOnUse"
primitiveUnits="userSpaceOnUse"
x="-100%" y="-100%"
width="300%" height="300%"
>
<feDropShadow dx="1" dy="2" stdDeviation="1" flood-color="black" flood-opacity="0.35"/>
</filter>
<filter
id="dropshadowSymbols"
filterUnits="userSpaceOnUse"
primitiveUnits="userSpaceOnUse"
x="-100%" y="-100%"
width="300%" height="300%"
>
<feDropShadow dx="4" dy="8" stdDeviation="4" flood-color="black" flood-opacity="0.35"/>
</filter>
<filter id="dropshadow2" x="-100%" y="-100%" width="300%" height="300%">
<feOffset result="offOut" in="SourceAlpha" dx="5" dy="8" />
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="1" />
<feComponentTransfer result="coloredOut" in="blurOut">
<feFuncA type="linear" slope="0.3"/>
<!--
<feFuncR type="table" tableValues="1 0"/>
<feFuncG type="linear" slope="0.0"/>
<feFuncB type="linear" slope="0.0"/>
-->
</feComponentTransfer>
<!--
<feComposite in="BackgroundImage" in2="coloredOut" operator="over" result="compOut"/>
<feBlend in="SourceGraphic" in2="coloredOut" mode="darken" />
-->
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
</svg>
<button id="mute">Mute</button>
<button id="start">Start</button>
<button id="reset">Reset</button>
<input type="checkbox" id="repeat" value="true">
SCSS
body {
margin: 50px;
background: #acbba8;
}
svg {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 400px;
height: 400px;
border: 1px solid red;
overflow: visible;
}
#clock {
//transform: translate(-50%, -50%);
}
symbol, use {
overflow: visible;
}
path.segment, circle {
fill: #a2b19e;
fill: rgba(0, 0, 0, 0.05);
&.on {
fill: #171b1e;
filter: url(#dropshadowSymbols);
}
}
path.circle-part {
stroke: #a2b19e;
stroke-width: 10;
fill: none;
stroke-linecap: butt;
&.on {
stroke: #171b1e;
filter: url(#dropshadow);
}
}
#mute {
position: fixed;
top: 50px;
right: 50px;
font-size: 20px;
}
#start {
position: fixed;
top: 50px;
left: 50px;
font-size: 20px;
}
#reset {
position: fixed;
top: 100px;
left: 50px;
font-size: 20px;
}
#repeat {
position: fixed;
top: 150px;
left: 50px;
width: 26px;
height: 26px;
}
JavaScript
function deg2rad(deg) {
return deg * (Math.PI/180);
}
function rad2deg(rad) {
return rad * (180/Math.PI);
}
var beep = (function() {
return function(duration, frequency, gain, finishedCallback) {
duration = +duration;
if (typeof finishedCallback != "function") {
finishedCallback = function () {};
}
var oscillatorNode = audioCtx.createOscillator();
oscillatorNode.type = "triangle"; // "sine", "triangle", "sawtooth", "square", "custom"
oscillatorNode.frequency.setValueAtTime(frequency, audioCtx.currentTime); // value in hertz
if (!gain) {
gain = 0.1;
}
var gainNode = audioCtx.createGain();
gainNode.gain.value = gain;
oscillatorNode.connect(gainNode);
if (!isMuted) {
gainNode.connect(audioCtx.destination);
}
if (oscillatorNode.noteOn) oscillatorNode.noteOn(0);
if (oscillatorNode.start) oscillatorNode.start();
setTimeout(function () {
if (oscillatorNode.noteOff) oscillatorNode.noteOff(0);
if (oscillatorNode.stop) oscillatorNode.stop();
finishedCallback();
}, duration);
};
})();
// Helper variables
var segs = [];
var pX = [];
var pY = [];
// Using arcs & set radius
function getRoundedCorner(prevP, curP, nextP, cc) {
var counterclockwise = cc || false;
if (counterclockwise) {
var tmp = prevP;
prevP = nextP;
nextP = tmp;
}
var aF = rad2deg(Math.atan2(pY[curP] - pY[prevP], pX[curP] - pX[prevP]));
var aT = rad2deg(Math.atan2(pY[nextP] - pY[curP], pX[nextP] - pX[curP]));
// Tangents of circle part
var rcF = aF - 90;
var rcT = aT - 90;
rcF += (rcF > 180? -360: (rcF < -180? 360: 0));
rcT += (rcT > 180? -360: (rcT < -180? 360: 0));
// Mid angle of tangent lines
var midA = (rcF + rcT) / 2;
// If straight line, don't use circle part
if (midA % 180 == 0 || r_inner == 0) {
return ['L', pX[curP], pY[curP]].join(' ');
}
// Half of angle difference
var halfDA = midA - rcF;
while (halfDA < 0) {
halfDA += 360;
}
// Relative position of corner to circle center
var distToCorner =...