<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG Animation</title>
<style>
svg, input {
display: block;
margin: 2px;
}
svg {
width: 200px;
height: 200px;
/*
stroke: #FFFFFF;
stroke-width: 2px;
*/
fill: transparent;
}
</style>
</head>
<body>
<input id="inputSec" type="number" placeholder="sec" value="10"/>
<button onclick="run()">Run</button>
<svg>
<circle id="crclBg" cx="100" cy="100" r="50" fill="#333333" stroke="#EEEEEE" stroke-width="9" stroke-dashoffset="0" stroke-dasharray="0"/>
<circle id="crclDp" cx="100" cy="100" r="50" fill="" stroke="#00cc44" stroke-width="9" stroke-dashoffset="0" stroke-dasharray="0"/>
<text id="txtSec" x="100" y="100" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2" font-size="30" text-anchor="middle" dominant-baseline="central"></text>
</svg>
<script>
// Simpler alternative to using SVG arcs: http://xahlee.info/js/svg_circle_arc.html
// More about dash arrays: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
const input = document.querySelector("#inputSec");
const circle = document.querySelector("#crclDp");
const text = document.querySelector("#txtSec");
// 1. Radius of SVG circle.
const radius = parseFloat(circle.getAttribute("r"));
const circumference = 2 * Math.PI * radius; // Circle's circumference
// 2. First, 1/4 of circumfence of 90 degrees. To start from top of the view,
// we must rotate it by 90 degrees. By default circle will start on the right.
// Stroke offset effectively rotates the circle.
const strokeOffset = (1 / 4) * circumference; // need to know 1/4 of the circumference
// 3. Rotate circle to start from the top.
circle.setAttribute("stroke-dashoffset", strokeOffset);
// 4. The length of visible dash, default 0.
let strokeDasharray = 0;
let angle = 0;
const draw = (arc) =>
{
angle = (angle >= 360) ? 0 : angle + arc;
// 4. Second, calculate dash array. We need dash array containing only two parts -
// visible dash, and invisible dash.
// Visible dash should have length of the chosen angle. Full circle is 360 degrees,
// and this 360 degrees does also equal the entire circumference. We want just a part of
// this entire circle to be visible - (angle / 360 degrees) returns a percentage value
// (between 0.0 and 1.0) of how much circumference should be visible.
// Hence, we then multiply (angle / 360) times the entire circumference.
strokeDasharray = (angle / 360) * circumference;
// 5. Create dash array of two elements (combined they must equal the entire circumference).
// First has the length of visible portion. Second, the remaining part.
circle.setAttribute("stroke-dasharray", [strokeDasharray, circumference - strokeDasharray]);
//console.log(angle);
}
const initCircle = () =>
{
angle = 360;
draw(0);
angle = 0;
}
let _sec = 0;
let _itvlTime;
let _loopCnt = 100; // loop time per 1 sec
let _itvlUnit = 1000 / _loopCnt; // 10/1000 milliseconds == 1/100 sec
const run = () =>
{
if (_itvlTime == null)
{
// initialize
initCircle();
let _accLoopCnt = 0;
_sec = parseInt(input.value);
text.textContent = _sec;
// loop (100 time per 1 sec)
_itvlTime = setInterval(() =>
{
++_accLoopCnt;
let _arc = 360 / (_sec * _loopCnt);
draw(_arc);
let _remainSec = parseInt(text.textContent);
if (_loopCnt == _accLoopCnt)
{
_accLoopCnt = 0;
--_remainSec;
text.textContent = _remainSec;
if (_remainSec <= 0)
{
clearInterval(_itvlTime);
_itvlTime = null;
}
//console.log(`${_accLoopCnt} : ${_remainSec}`);
}
}, _itvlUnit);
}
}
window.onload = function()
{
// initialize
initCircle();
}
</script>
</body>
</html>