A concentric Count Down Timer adapted from Mike Bostock's "Arc Tween (clock)".
All it needs is pause functionality and the text input boxes to be centered in the middle, if only there was svg input boxes.. Or alternatively could have d3 brushes in the center instead, similar to HTML5 ranges. Or even better add drag functionality to the indivdual time bar -> something to do.
xxxxxxxxxx
<!-- code is adapted from:
https://gist.github.com/mbostock/1098617
-->
<html lang="en">
<head>
<meta charset="utf-8">
<title>Count Down Timer</title>
<script src="https://d3js.org/d3.v3.min.js"></script>
</head>
<style type="text/css">
#chartArea {
border: 2px dashed black;
height: 500px;
width: 500px;
}
path {
fill-rule: evenodd;
fill: #aaa;
fill-opacity: .7;
stroke: #666;
stroke-width: 5.5px;
}
#valueOutput{
fill:maroon;
}
</style>
<body>
<div id="chartArea">
<form> <!-- try using sliders + put in center of arc-->
Hours: <input type="number" name="hour" value="15" style="width: 100px">
Minutes: <input type="number" name="minute" value="45" style="width: 100px">
Seconds: <input type="number" name="second" value="25" style="width: 100px">
</form>
</div>
</body>
<script type="text/javascript">
var divH = parseInt( d3.select("#chartArea").style("height") );
var divW = parseInt( d3.select("#chartArea").style("width") );
var margin = {top: 10, right: 10, bottom: 10, left: 10};
var w = divW - margin.left - margin.right;
h = divH - margin.top - margin.bottom;
x = d3.scale.ordinal().domain(d3.range(3)).rangePoints([0, w], 2);
var initSeconds = document.getElementsByName("second")[0].value;
var initMinutes = document.getElementsByName("minute")[0].value;
var initHours = document.getElementsByName("hour")[0].value;
var fields = [
{name: "seconds", value: initSeconds, size: 60, order: 0},
{name: "minutes", value: initMinutes, size: 60, order: 1},
{name: "hours", value: initHours, size: 24, order: 2}
];
var outerRadiusInit = w / 2.2;
var arcWidth = 35;
var innerRadiusInit = outerRadiusInit - arcWidth;
var arc = d3.svg.arc()
.innerRadius(function(d) { return innerRadiusInit - d.order * arcWidth ; })
.outerRadius(function(d) { return outerRadiusInit - d.order * arcWidth ; })
.startAngle(0)
.endAngle(function(d) { return (d.value / d.size) * 2 * Math.PI; });
var svg = d3.select("#chartArea").append("svg:svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("svg:g")
.attr("transform", "translate(" + margin.left + "," +(margin.top + h/2)+ ")");
svg.append("text")
.attr("id", "valueOutput")
.attr("text-anchor", "middle")
.attr("transform","translate(" + w / 2 + ",0)");
setInterval(function() {
fields[0].previous = fields[0].value;
fields[1].previous = fields[1].value;
fields[2].previous = fields[2].value;
document.getElementsByName("second")[0].value -= 1;
if(document.getElementsByName("second")[0].value <= 0){
document.getElementsByName("second")[0].value = 60;
document.getElementsByName("minute")[0].value -= 1;
}
if(document.getElementsByName("minute")[0].value <= 0){
document.getElementsByName("minute")[0].value = 60;
document.getElementsByName("hour")[0].value -= 1;
}
//maybe I should have done this before all the logic above...but then I would have to do it twice...
fields[0].value = document.getElementsByName("second")[0].value;
fields[1].value = document.getElementsByName("minute")[0].value;
fields[2].value = document.getElementsByName("hour")[0].value;
var timeString = fields[2].value + ":" + fields[1].value + ":" + fields[0].value ;
d3.select('#valueOutput').html(timeString);
var path = svg.selectAll("path")
.data(fields.filter(function(d) { return d.value; }), function(d) { return d.name; });
path.enter().append("svg:path")
.attr("transform", function(d, i) { return "translate(" + h/2 + ",0)"; })
.transition()
.ease("linear")
.duration(1000)
.attrTween("d", arcTween);
path.transition()
.ease("linear")
.duration(1000)
.attrTween("d", arcTween);
path.exit().transition()
.ease("ease")
.duration(750)
.attrTween("d", arcTween)
.remove();
}, 1000);
function arcTween(b) {
var i = d3.interpolate({value: b.previous}, b);
return function(t) {
return arc(i(t));
};
}
</script>
</html>
https://d3js.org/d3.v3.min.js