相信大家都用过google身份验证器,每30s刷新一次,然后更新6位验证码。今天我们就来写一个它的计时器。它有一个特点就是:第一圈并不是从30s开始计时,可能是26s,也可能是11s,完全跟当前时间有关系。所以我们要用Date.now()取值。效果如下:
1.html
我们需要2个canvas,一个作为前景,一个作为背景,前景每秒绘制一次,背景只绘制一次。
<div class='wrap'>
<canvas class='canvas front' width='200' height='200'></canvas>
<canvas class='canvas back' width='200' height='200'></canvas>
</div>
2.css
使前景和背景分层,不然前景会覆盖掉背景,背景不显示。
.wrap{
position:relative;
}
/* 使其脱离文档流 */
.front{
z-index:100;
position:absolute;
}
.back{
position:absolute;
left:0px;
right:0px;
}
3.前景
前景画很多次,需传入参数
function drawCircle(n){
if(n == 0) n = 30;
context.beginPath();
context.strokeStyle = '#508bd9';
context.lineWidth = 20;
context.arc(centerX,centerY,50,-Math.PI/2, -Math.PI/2 + n*rad,true);
//显示数字
context.fillStyle = "#555";
context.font = '30px Arial';
context.textAlign = "center";
context.textBaseline = "middle";
context.fillText((30-n==0?30:30-n),centerX ,centerY);
context.stroke();
}
4.背景
背景只画一次
function drawBackCircle(){
var backCanvas = document.getElementsByClassName('canvas')[1],
cxt = backCanvas.getContext('2d');
cxt.save();
cxt.beginPath();
cxt.strokeStyle = "#eee";
cxt.lineWidth = 20;
cxt.arc(centerX,centerY,50,-Math.PI/2, 3 * Math.PI/2,true);
cxt.stroke();
}
5.定时器
循环绘制前景,使用setTimout()
function setTimer() {
if(timer){
clearTimeout(timer);
}
context.clearRect(0, 0, canvas.width, canvas.height); //清除前景
var speed = Math.floor(Date.now() / 1000 % 30); //取当前时间,每30s一圈
drawCircle(speed); //绘制前景
var timer = setTimeout(function(){
setTimer();
},1000);
}
codepen完整版
可以打开你的google身份验证器和codepen地址看看,时间是不是同步的呢,哈哈。也可以缩短定时器的时间间隔,让它转得更像动画。
如果有错误,请指出。