基于canvas实现计时器,请酷的哟,有源码分享

先贴两张效果图,如果你喜欢可以进一步了解源码  


timer.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>计时器</title>
    <meta name="description" content="计时器,秒表,timer,超级好用的计时器">
    <meta name="Keywords" content="计时器,秒表,timer,超级好用的计时器">
    <meta name="author" content="alioo <lzc.java@icloud.com>">
    <link rel="stylesheet" href="timer.css">
    <script type="text/javascript" src="jquery-1.11.1.js"></script>
    <script>
        var _hmt = _hmt || [];
        (function() {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?0650df3b90de1b6a01acc72869daf305";
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(hm, s);
        })();
    </script>

</head>
<body>
<div class="page clearfix">

    <div class="lf message">
        <!-- 定义canvas画布,包括宽度和高度,还有背景颜色 -->
        <canvas id="clock" width="800" height="800" style="background:black">
            你的浏览器不支持canvas标!
        </canvas>
    </div>
    <div class="lf history">
        <div class="history-title">最近20条计时记录</div>
        <div class="history-data">
            <!--<div><span class="history-tip">1</span><span class="history-text">00:00.738<span class='tip'>双击删除我吧</span></span></div>-->
            <!--<div><span class="history-tip">1</span><span class="history-text">00:00.738<span class='tip'>双击删除我吧</span></span></div>-->
            <!--<div><span class="history-tip">15</span><span class="history-text">00:00.738<span class='tip'>双击删除我吧</span></span></div>-->
            <!--<div><span class="history-tip">16</span><span class="history-text">00:00.738<span class='tip'>双击删除我吧</span></span></div>-->
        </div>
    </div>
    <div class="lf statistic">
        <div class="statistic-title">统计数据</div>
        <div class="statistic-data none">
            <div class="fast">最快用时<span></span></div>
            <div class="slow">最慢用时<span></span></div>
            <div class="average">平均用时<span></span></div>
        </div>
    </div>
</div>

<script src="timer.js" type="text/javascript"></script>
</body>
</html>


timer.js

//获取上下文文档对象
var clock = document.getElementById('clock');
var ctx = clock.getContext('2d');

//仪表盘中心点坐标及半径
var pointX = 400;
var pointY = 400;
var R = 300;

/***
 * 画指针
 * @param linewidth 画线的宽度,即粗细
 * @param linecolor 画线的颜色
 * @param angle 角度
 * @param idx   角度基数,angle*idx为本次真实需要旋转的角度
 * @param startx
 * @param starty
 * @param endx
 * @param endy
 */
function drawPointer(linewidth, linecolor, angle, idx, startx, starty, endx, endy) {
    ctx.save();                  //先保存当前画布
    ctx.lineWidth = linewidth;      //设置画笔的宽度
    ctx.strokeStyle = linecolor;    //设置画笔的颜色
    ctx.translate(pointX, pointY);     //重置异次元空间的原点坐标
    ctx.rotate(angle * idx * Math.PI / 180);  //设置旋转的角度,参数是弧度
    // console.log(angle,idx,angle * idx * Math.PI / 180);
    ctx.beginPath();
    ctx.moveTo(startx, starty);
    ctx.lineTo(endx, endy);
    ctx.closePath();            //先闭合路径,再画线
    ctx.stroke();               //开始画线
    ctx.restore();              //将旋转后的线段返回给画布
}

/***
 * 画刻度
 * @param linesize  总共画linesize条线
 * @param linewidth 线的宽度,即粗细
 * @param linecolor 画线的颜色
 * @param angle     角度
 * @param startx
 * @param starty
 * @param endx
 * @param endy
 */
function drawScale(linesize, linewidth, linecolor, angle, startx, starty, endx, endy) {
    for (var idx = 0; idx < linesize; idx++) {
        drawPointer(linewidth, linecolor, angle, idx, startx, starty, endx, endy);
    }
}

//画表盘的中心点, 黑实心,红色边框
function drawFill() {
    ctx.save();
    ctx.lineWidth = 2;      //设置画笔的宽度
    ctx.strokeStyle = "#ff0000";    //设置画笔的颜色
    ctx.beginPath();
    ctx.arc(pointX, pointY, 4, 0, Math.PI * 2, false); //arc方法:画圆或者画弧
    ctx.closePath();
    ctx.fillStyle = "#000000";
    ctx.fill();
    ctx.stroke();
    ctx.restore();
}

/**
 * 绘制仪表盘上的数字
 */
function drawNumber() {
    //绘制仪表盘上的数字
    for (var i = 1; i <= 12; i++) {
        var text = i * 5;
        var radian = (i * 30) * (Math.PI * 2 / 360);
        var R = 240;
        var offsetX = -17;
        var offsetY = 4;
        var x = Math.sin(radian) * R + offsetX; //不加上offset会发现所有内容均向在偏移了一些,可能是文字下标定位有关
        var y = -Math.cos(radian) * R + offsetY;

        ctx.save();
        ctx.translate(pointX, pointY);     //重置异次元空间的原点坐标
        //设置字体样式
        ctx.font = "600 30px Courier New";
        // //设置字体填充颜色
        ctx.fillStyle = "white";
        //从坐标点(50,50)开始绘制文字
        ctx.fillText("" + text, x, y);
        ctx.restore();
    }
}

/**
 * 绘制仪表盘上的数字
 */
function drawData(formatObj) {
    var text=formatObj.mm+":"+formatObj.ss+"."+formatObj.sss;

    //绘制仪表盘上的数字
    var x = -60;
    var y = 100;

    ctx.save();
    ctx.translate(pointX, pointY);     //重置异次元空间的原点坐标
    //设置字体样式
    ctx.font = "600 25px Courier New";
    // //设置字体填充颜色
    ctx.fillStyle = "white";
    //从坐标点(50,50)开始绘制文字
    ctx.fillText("" + text, x, y);
    ctx.restore();
}

//画时钟
function drawClock(startTime, endTime, formatObj) {
    ctx.clearRect(0, 0, 800, 800);  //清空整个画布

    var diffTime = endTime - startTime;
    var sec = Math.floor(diffTime % 60000 / 1000);
    var milliSec = diffTime % 1000;
    var milliSecFix = sec * 5 + milliSec / 200; //仪表盘每200ms一个刻度,每1s五个刻度
    // console.log(diffTime, sec, milliSec, milliSecFix);

    drawNumber(); //刻度上面的数字
    drawScale(300, 2, "#4c4c4c", 1.2, 0, 270, 0, 280);      //画1/5秒刻度,每秒再分5档
    drawScale(60, 2, "#ffffff", 6, 0, 260, 0, 280);         //画秒刻度

    drawPointer(2, "red", 1.2, milliSecFix, 0, 30, 0, -280);       //画秒针

    drawFill(); //画表盘的中心点
    drawData(formatObj); //计时器启动后使用的时间
}



/***************定时器相关********************************/
var jishiqiTimer;  //timer
var startTime;     //记录每次启动计时器的开始时间
var formatObj = {};//格式化对象
var formatObjArr=[];
var formatObjArr=[];

//初始化
formatObj = formatTime(0, 0);
drawClock(0, 0,formatObj);

function mystart() {
    var endTime = new Date().getTime();
    //format
    var formatObj = formatTime(startTime, endTime);
    console.log(formatObj)
    drawClock(startTime, endTime,formatObj);

    // jishiqiDiv.html(str);
}
function formatTime(startTime, endTime) {
    var difftime = endTime - startTime;
    return doFormatTime(difftime);
}
function doFormatTime(difftime) {
    if (difftime > 3600000) { //此计时器最多只算处理60分钟
        formatObj.mm = "60";
        formatObj.ss = "00";
        formatObj.sss = "000";
        formatObj.difftime=3600000;
        return formatObj ;
    }
    var mm;
    var ss;
    var sss;
    if (difftime >= 60000) {
        mm = Math.floor(difftime / 60000) + ""; //Math.floor()目的是为了向下取整, +""目的为了转成字符串
        ss = Math.floor(difftime % 60000 / 1000) + "";
        sss = Math.floor(difftime % 1000) + "";
    } else if (difftime >= 1000) {
        mm = "00";
        ss = Math.floor(difftime % 60000 / 1000) + "";
        sss = Math.floor(difftime % 1000) + "";
    } else {
        mm = "00";
        ss = "00";
        sss = difftime + "";
    }
    mm = buquan(mm, 2);
    ss = buquan(ss, 2);
    sss = buquan(sss, 3);


    formatObj.mm = mm;
    formatObj.ss = ss;
    formatObj.sss = sss;
    formatObj.difftime=difftime;
    return formatObj;
}

function buquan(a, length) {
    while (a.length < length) {
        a = "0" + a;
    }
    return a;
}
function showHistoryData() {
    var historyDataDiv=$(".history-data");
    historyDataDiv.html("");
    $.each(formatObjArr,function (i, obj) {
        var text=obj.mm+":"+obj.ss+"."+obj.sss;
        var str="<div><span class='history-tip'>"+(i+1)+"</span><span class='history-text'>" + text + "</span></div>"
        historyDataDiv.append(str);
    })
}
function addHistory(formatObj) {
    if(formatObj.mm=="00"&&formatObj.ss=="00"&&formatObj.sss=="000"){
        return;
    }
    var tempObj=$.extend({},formatObj);
    formatObjArr.push(tempObj);
    if(formatObjArr.length>20){ //缓存最多只存20条
        formatObjArr.splice(0,formatObjArr.length-20);
    }
}


function statisticHistory() {
    if(formatObjArr.length==0){
        $(".statistic-data .fast span").text("00:00.000");
        $(".statistic-data .slow span").text("00:00.000");
        $(".statistic-data .average span").text("00:00.000");
        return;
    }
    $(".statistic-data").removeClass("none");
    var fast={};
    var slow={};
    var average={};
    var total=0;
    $.each(formatObjArr,function (i, obj) {
        if(!fast.difftime){ //第1次遍历的时候fast、slow均没有初始化值
            fast=obj;
        }
        if(!slow.difftime){
            slow=obj;
        }
        if(obj.difftime<fast.difftime){
            fast=obj;
        }
        if(obj.difftime>slow.difftime){
            slow=obj;
        }
        total+=obj.difftime;

    });
    var averageDifftime=Math.round(total/formatObjArr.length);
    average=doFormatTime(averageDifftime);

    var fasttext=fast.mm+":"+fast.ss+"."+fast.sss;
    var slowtext=slow.mm+":"+slow.ss+"."+slow.sss;
    var averagetext=average.mm+":"+average.ss+"."+average.sss;
    $(".statistic-data .fast span").text(fasttext);
    $(".statistic-data .slow span").text(slowtext);
    $(".statistic-data .average span").text(averagetext);
}

//事件相关
$(".history-data").on("mouseover",".history-text",function(){
    var historyDataOne=$(this);
    if(historyDataOne.find(".tip").length==0){
        historyDataOne.append("<span class='tip'>双击删除我吧</span>");
    }
});
$(".history-data").on("mouseout",".history-text",function(){
    var historyDataOne=$(this);
    if(historyDataOne.find(".tip").length>0){
        historyDataOne.find(".tip").remove();
    }
});
$(".history-data").on("dblclick",".history-text",function(){
    var historyDataOne=$(this);
    if(historyDataOne.find(".tip").length>=0){
        //
        var idx=parseInt(historyDataOne.parent().find('.history-tip').text())-1;
        formatObjArr.splice(idx,1);

        showHistoryData();
        statisticHistory();
    }
});
$(document).keydown(function (event) {
    if (event.keyCode != 32 && event.keyCode != 13) { //空格 或者 回车
        return;
    }
    if (jishiqiTimer != null) {
        clearInterval(jishiqiTimer);
        jishiqiTimer = null;
        addHistory(formatObj);

        showHistoryData();
        statisticHistory();
    } else {
        startTime = new Date().getTime();
        jishiqiTimer = setInterval(mystart, 123);
    }

});

timer.css
 
* {
    margin: 0;
    padding: 0;
}
.none{
    display: none !important;
}
/**实际测试使用伪类清除浮动时需要加上content:" ";display:block;这两句话*/
.clearfix:after {
    content:" ";
    display:block;
    clear: both;
}
.tip{
    /*display: none;*/
    position: absolute;
    font-size: 12px;
    line-height:30px;
    padding-left: 5px;
}

body{
    background: #000000;
}
.lf {
    float: left;
    /*text-align: center;*/
}
.history , .statistic{
    width: 230px;
    min-height: 650px;
    color: #ffffff;
    margin-top: 70px;
    border-left: 1px solid #f0f0f0;
}
.history .history-title,.statistic .statistic-title{
    padding-bottom: 20px;
    padding-left: 10px;
    font-size: 22px;
    color: #ffffff;
}
.history .history-data,.statistic .statistic-data{
    font-size: 20px;
    text-align: left;
    padding-left: 10px;
}
.history-data .history-tip{
    display: inline-block;
    width: 30px;
    height: 30px;
    line-height: 30px;
    text-align: right;
    color: #FF2F2F;
    padding-right: 10px;
}

.history-data .history-text{
    display: inline-block;
    width: 160px;
    height: 30px;
    line-height: 30px;
    color: #ffffff;
    cursor: pointer;
    padding-left: 10px;
}
.history .history-data .history-text:hover{
    border-bottom: 1px solid #fff;
}
.statistic .statistic-data div{
    height: 30px;
    line-height: 30px;
}
.statistic .statistic-data div span{
    padding-left: 10px;
}








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值