canvas timecount
last update:
2020/12/19
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>title</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<style>
.circles {
overflow: hidden;
}
.year, .day, .hour, .minute, .second {
float: left;
position: relative;
margin: 0 4px;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.fadeIn {
animation-name: fadeIn;
animation-duration: .7s;
}
.fadeOut {
animation-name: fadeOut;
animation-duration: .7s;
}
.diff {
opacity: 1;
}
.prev {
opacity: 0;
}
.diff, .prev {
width: 100%;
position: absolute;
top: 38px;
text-align: center;
font-size: 44px;
line-height: 44px;
}
.diff + span {
display: block;
width: 100%;
position: absolute;
top: 86px;
text-align: center;
font-size: 11px;
line-height: 14px;
}
.information {
font-size: 12px;
}
</style>
</head>
<body>
<div class="information" style="margin-bottom: 20px;">
<div class="target">target: <span></span></div>
<div class="targetMil">targetMil: <span></span></div>
<div class="nowMil">nowMil: <span></span></div>
<div class="diffMil">diffMil: <span></span></div>
<div class="digits">digits: <span></span></div>
</div>
<div class="countdown">
<div class="circles">
<div class="year">
<canvas class="canvas" width="" height=""></canvas>
<div class="prev"></div>
<div class="diff"></div>
<span>---<br>99<br>year</span>
</div>
<div class="day">
<canvas class="canvas" width="" height=""></canvas>
<div class="prev"></div>
<div class="diff"></div>
<span>---<br>365<br>day</span>
</div>
<div class="hour">
<canvas class="canvas" width="" height=""></canvas>
<div class="prev"></div>
<div class="diff"></div>
<span>---<br>24<br>hour</span>
</div>
<div class="minute">
<canvas class="canvas" width="" height=""></canvas>
<div class="prev"></div>
<div class="diff"></div>
<span>---<br>60<br>min</span>
</div>
<div class="second">
<canvas class="canvas" width="" height=""></canvas>
<div class="prev"></div>
<div class="diff"></div>
<span>---<br>60<br>sec</span>
</div>
</div>
</div>
<script>
(function (w, d) {
const targetDate = new Date('January 1, 2110 10:00:00'); // target date and time
let squareX = 320; // width of canvas (retina)
let squareY = 320; // height of canvas (retina)
let centerX = 160; // center of circle X (retina)
let centerY = 160; // center of circle Y (retina)
let radius = 150; // radius of circle (retina)
let lineWeightBack = 4; // line weight of gray circle (retina)
let lineWeightCount = 10; // line weight of count circle (retina)
// get DOM & set param
const data = [
{
canvas: d.querySelector('.year .canvas'),
diff: d.querySelector('.year .diff'),
prev: d.querySelector('.year .prev'),
full: 99,
changeFlag: false,
},
{
canvas: d.querySelector('.day .canvas'),
diff: d.querySelector('.day .diff'),
prev: d.querySelector('.day .prev'),
full: 365,
changeFlag: false,
},
{
canvas: d.querySelector('.hour .canvas'),
diff: d.querySelector('.hour .diff'),
prev: d.querySelector('.hour .prev'),
full: 24,
changeFlag: false,
},
{
canvas: d.querySelector('.minute .canvas'),
diff: d.querySelector('.minute .diff'),
prev: d.querySelector('.minute .prev'),
full: 60,
changeFlag: false,
},
{
canvas: d.querySelector('.second .canvas'),
diff: d.querySelector('.second .diff'),
prev: d.querySelector('.second .prev'),
full: 60,
changeFlag: false,
},
];
// set canvas size
data.map((e) => {
e.canvas.setAttribute('width', squareX);
e.canvas.setAttribute('height', squareY);
e.canvas.setAttribute('style', 'width: ' + squareX / 2 + 'px; height: ' + squareY / 2 + 'px;');
});
// make two digits
const shapeValue = (value) => ('0' + Math.floor(value)).slice(-2);
// make three digits
const shapeValueThree = (value) => ('00' + Math.floor(value)).slice(-3);
// make diffSet and prevSet
const pushValue = (set, time) => {
set.push(shapeValue(time / 1000 / 60 / 60 / 24 / 365));
set.push(shapeValueThree(time / 1000 / 60 / 60 / 24 % 365));
set.push(shapeValue(time / 1000 / 60 / 60 % 24));
set.push(shapeValue(time / 1000 / 60 % 60));
set.push(shapeValue(time / 1000 % 60));
};
// print digit to DOM
const printDiff = (callback) => {
const nowDate = new Date();
const diff = targetDate - nowDate;
const prev = diff + 1000;
let diffSet = [];
let prevSet = [];
if (diff >= 0) {
pushValue(diffSet, diff);
pushValue(prevSet, prev);
} else {
diffSet = ['00', '000', '00', '00', '00'];
prevSet = ['00', '000', '00', '00', '00'];
}
for (let i = 0; i < data.length; i++) {
if (data[i].diff.innerHTML === diffSet[i]) {
data[i].changeFlag = false;
} else {
data[i].changeFlag = true;
data[i].diff.innerHTML = diffSet[i];
data[i].prev.innerHTML = prevSet[i];
data[i].diff.classList.add('fadeIn');
data[i].prev.classList.add('fadeOut');
w.setTimeout(function () {
data[i].diff.classList.remove('fadeIn');
data[i].prev.classList.remove('fadeOut');
}, 900);
}
}
callback(data);
// for test
const info = {
target: d.querySelector('.information .target span'),
targetMil: d.querySelector('.information .targetMil span'),
nowMil: d.querySelector('.information .nowMil span'),
diffMil: d.querySelector('.information .diffMil span'),
digits: d.querySelector('.information .digits span'),
}
info.target.innerHTML = targetDate;
info.targetMil.innerHTML = targetDate.getTime();
info.nowMil.innerHTML = nowDate.getTime();
info.diffMil.innerHTML = diff;
info.digits.innerHTML = diffSet[0] + ' ' + diffSet[1] + ' ' + diffSet[2] + ' ' + diffSet[3] + ' ' + diffSet[4];
};
// drow circle on canvas
const drowCircle = (data) => {
let endPointPer;
let endPoint;
let canvas;
let context;
let rotate;
let posStart;
let posEnd;
let contextColor;
data.forEach((e) => {
if (e.changeFlag !== true) {
return;
}
startPointPer = (e.full - Number(e.diff.innerHTML)) / e.full * 100;
startPoint = 360 / 100 * startPointPer;
canvas = e.canvas;
if (!canvas || !canvas.getContext) {
return false;
}
context = canvas.getContext('2d');
rotate = -90;
posStart = startPoint + rotate;
posEnd = 0 + rotate;
context.clearRect(0, 0, squareX, squareY);
context.beginPath();
context.arc(centerX, centerY, radius, 0 * Math.PI / 180, 360 * Math.PI / 180, false);
context.strokeStyle = '#eee';
context.lineWidth = lineWeightBack;
context.stroke();
if (posStart === 270) {
return;
}
context.beginPath();
context.arc(centerX, centerY, radius, posStart * Math.PI / 180, posEnd * Math.PI / 180, false);
contextColor = context.createLinearGradient(120, 30, 30, 120);
contextColor.addColorStop(0.0, '#ccc');
contextColor.addColorStop(1.0, '#ccc');
context.strokeStyle = contextColor;
context.lineWidth = lineWeightCount;
context.stroke();
return true;
});
};
// background control
let id;
d.addEventListener('webkitvisibilitychange', () => {
if (d.webkitHidden) {
clearInterval(id);
} else {
init(new Date());
}
}, false);
// init
const init = (backgroundControl) => {
printDiff(drowCircle);
id = setInterval(() => {
printDiff(drowCircle);
if (targetDate < backgroundControl) {
clearInterval(id);
}
}, 1000);
};
init(new Date());
})(window, document);
</script>
</body>
</html>
code_popup