Skip to content

Instantly share code, notes, and snippets.

@lsquaredleland
Last active August 14, 2016 08:53
Show Gist options
  • Save lsquaredleland/e068c5fc42294089b55b to your computer and use it in GitHub Desktop.
Save lsquaredleland/e068c5fc42294089b55b to your computer and use it in GitHub Desktop.
Concentric Count Down Timer

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.

<!-- code is adapted from:
https://gist.github.com/mbostock/1098617
-->
<!DOCTYPE html>
<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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment