Time timer by d3.js v4
simply input minutes and you can see how many time remains through visual block
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<title></title> | |
<link rel="stylesheet" href="time.css"> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script> | |
</head> | |
<body> | |
<div class="container"> | |
<div class='chart'></div> | |
<label for="fname">Time (minutes)</label> | |
<input type="number" id="time" name="time"> | |
</div> | |
<script src="timer.js"></script> | |
</body> | |
</html> |
.container { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
flex-direction: column; | |
} | |
input[type=number] { | |
border: 2px solid red; | |
border-radius: 4px; | |
margin-top: 10px; | |
} | |
.chart { | |
width: 100%; | |
height:100%; | |
text-align: center; | |
} |
// Data setting | |
const timeData = (time, sec) => { | |
let second = sec; | |
return [ | |
{ | |
"unit": "seconds", | |
"numeric": second | |
}, { | |
"unit": "minutes", | |
"numeric": time | |
} | |
]; | |
}; | |
// value setting | |
let width = 300; | |
let height = 200; | |
let offSetX = 150; | |
let offSetY = 100; | |
let pi = Math.PI; | |
let scaleSecs = d3.scaleLinear().domain([0, 59 + 999/1000]).range([0, 2 * pi]); | |
let scaleMins = d3.scaleLinear().domain([0, 59 + 59/60]).range([0, 2 * pi]); | |
let vis = d3.selectAll(".chart") | |
.append("svg:svg") | |
.attr("width", width) | |
.attr("height", height); | |
let clockGroup = vis.append("svg:g") | |
.attr("transform", "translate(" + offSetX + "," + offSetY + ")"); | |
clockGroup.append("svg:circle") | |
.attr("r", 80).attr("fill", "none") | |
.attr("class", "clock outercircle") | |
.attr("stroke", "black") | |
.attr("stroke-width", 2); | |
clockGroup.append("svg:circle") | |
.attr("r", 4) | |
.attr("fill", "black") | |
.attr("class", "clock innercircle"); | |
// render clock | |
const render = (data) => { | |
let minuteArc, secondArc; | |
clockGroup.selectAll(".clockhand").remove(); | |
secondArc = d3.arc() | |
.innerRadius(0) | |
.outerRadius(70) | |
.startAngle((d) => { | |
return scaleSecs(d.numeric); | |
}) | |
.endAngle((d) => { | |
return scaleSecs(d.numeric); | |
}); | |
minuteArc = d3.arc() | |
.innerRadius(0) | |
.outerRadius(80) | |
.startAngle((d) => { | |
return 0; | |
}) | |
.endAngle((d) => { | |
return scaleMins(d.numeric); | |
}); | |
clockGroup.selectAll(".clockhand") | |
.data(data) | |
.enter() | |
.append("svg:path") | |
.attr("d", (d) => { | |
if (d.unit === "seconds") { | |
return secondArc(d); | |
} else if (d.unit === "minutes") { | |
return minuteArc(d); | |
} | |
}) | |
.attr("class", "clockhand") | |
.attr("stroke", "black") | |
.attr("stroke-width", function(d) { | |
if (d.unit === "seconds") { | |
return 2; | |
} else if (d.unit === "minutes") { | |
return 3; | |
} | |
}) | |
.attr("fill", "red") | |
.attr("opacity", "0.8"); | |
}; | |
let timer; | |
const startTimer = (e) => { | |
// Main program | |
clearInterval(timer); | |
let data; | |
let timeAsSec = e.target.valueAsNumber * 60; | |
let sec = 0; | |
timer = setInterval(() => { | |
sec = sec + 1; | |
timeAsSec = timeAsSec - 1; | |
data = timeData(timeAsSec / 60, sec); | |
render(data); | |
if (timeAsSec === 0) { | |
clearInterval(timer); | |
} | |
}, 1000); | |
}; | |
let timeInput = document.querySelector('#time'); | |
timeInput.addEventListener("change", startTimer); |