• html5入门:教你用canvas写一个时钟


      今天的时间比较充裕,心血来潮,为大家分享一个html5的小例子,希望对刚学html5或者是没学html5正准备学的“童鞋们”展示一个小案例,希望对你们的学习有帮助!高手嘛!请跳过吧!

      好了,闲话少数,先看看一下我们的案例效果图吧!

      

      哦哦,我的时间暴露了!效果很粗糙,没有美化,有兴趣的朋友可以写的好看一点!

      好了, 这是用什么写的呢,这大家都知道,肯定是html5 的canvas标签和js共同完成的啦,利用canvas的绘图的属性画一个一个的形状,现在就跟我一起画吧!

      分析:时钟包括  表盘,小时刻度,分钟刻度,时针,分针,秒针

      首先当然是html5声明,声明很简单,就一行:

      

    <!doctype html>
    

      doctype可与的大写,也可以是小写,也可以是大小写,这都无所谓,看你自己的习惯(不区分大小写);头部我就不写了,我会将源码附到下面,为节约时间,我就开始讲正文,头部也没什么好将的

      

    <canvas width="500" height="500" style="background:yellow; margin:50px auto; display:block; " id="clock">
         您的浏览器当前版本不支持canvas表签
    </canvas>
    

      在body里面写一个canvas标签,设置宽高为500,500(ps:设置宽高时建议按照上面的写法给,不是说在样式表里面不能给,在样式表里面给宽高,在绘图时图形的位置会出错),背景颜色设为黄色;

    开始绘图了:

    <script>
        //获取画布DOM 还不可以操作
        var canvas = document.getElementById('canvas');
        //设置绘图环境
        var cxt = canvas.getContext('2d');
    </script>

    先获取canvas DOM, 设置绘图环境,目前还只有2d;
    (为节省版面,js部分拆分的部分不加script标记了)

    画表盘:

    //表盘(蓝色)
    cxt.beginPath();  //画笔开始
    cxt.lineWidth = 5;  //设置画笔的线宽
    cxt.strokeStyle="blue";  //设置画笔的颜色
    cxt.arc(250,250,200,0,360,false);  //绘制圆形,坐标250,250 半径200,整圆(0-360度),false表示顺时针
    cxt.stroke();   //绘图
    cxt.closePath();  //结束画布

    写有注释,看得懂不,解释一下,画形状一般都需要写一个开始画笔和结束画布,你自己写一下,看看效果你就知道了,这是画的空心圆,效果是这样的:

    然后我们开始画刻度,刻度有小时刻度和分针刻度,先画小时刻度吧:

    //时针刻度
    for(var i=0; i<12; i++){
    cxt.save();   //设置旋转环境
    //设置时针的样式
    cxt.lineWidth=7;
    cxt.strokeStyle="#000";
    
    cxt.translate(250,250);//设置异次元空间的原点
    
    cxt.rotate(30*Math.PI/180);//设置旋转角度
    cxt.beginPath();  //画笔开始
    cxt.moveTo(0,-170);   //画线, 从坐标0,-170开始
    cxt.lineTo(0,-190);   //到坐标0,-190结束
    cxt.stroke();   //绘图
    cxt.closePath();
    cxt.restore();  //将旋转之后的元素放回原画布
    }


    因为小时刻度是要在表盘上旋转分布的,所以我们要设一个中心原点,以原点为中心,表针可以旋转指向某个时刻,当然,刻度不只有一个,所以我们用for循环的方式,画出12条线段,旋转角度说明一下,弧度 = 角度*Math.PI/180,要是你有兴趣,可以查一下这是怎么来的(数学里有),一周有12个刻度,一个刻度就是30°;

    效果如图:

    画分刻度,原理跟时刻的是一样的,只是角度不一样:

    //分针刻度
    for(var i=0; i<60;i++){
    cxt.save();
    cxt.lineWidth=5;
    cxt.strokeStyle="#000";
    cxt.translate(250,250);
    cxt.rotate(6*Math.PI/180);
    cxt.beginPath();
    cxt.moveTo(0,-180);
    cxt.lineTo(0,-190);
    cxt.stroke();
    cxt.closePath();
    cxt.restore();    
    }

    注释就不写了,跟上面的是一样的
    效果如图:

    现在开始画指针了,先画时针吧:

    //时针
    cxt.save();  //设置旋转环境
    //时针样式
    cxt.lineWidth = 7;
    cxt.strokeStyle="#000";
    cxt.translate(250,250); //设置异次元空间原点
    cxt.rotate(30*Math.PI/180);  //设置旋转角度
    cxt.beginPath();   //画笔开始
    cxt.moveTo(0,-140);  //画线, 从坐标0,-140开始
    cxt.lineTo(0,10);   //到坐标0,10结束
    cxt.stroke();   //绘图
    cxt.closePath();   //结束画布
    cxt.restore();   //将旋转之后的元素放回原画布

    时针现在实际上就是画一个直线,因为要旋转,所以是在异次元空间设置原点

    效果如图:

    那分针和秒针就一样一样的了,稍微给点变化,比如给长一点,指针细一点

    //分针
    cxt.save();
    //分针样式
    cxt.lineWidth = 5;
    cxt.strokeStyle="#000";
    cxt.translate(250,250);
    cxt.rotate(6*Math.PI/180);
    cxt.beginPath();
    cxt.moveTo(0,-160);
    cxt.lineTo(0,15);
    cxt.stroke();
    cxt.closePath();
    cxt.restore();

    对照时针看注释,这里就不写注释了
    效果如图:

    现在写分针:

    //秒针
    cxt.save();
    cxt.lineWidth = 3;
    cxt.strokeStyle="#f00";
    cxt.translate(250,250);
    cxt.rotate(60*Math.PI/180);
    cxt.beginPath();
    cxt.moveTo(0,-185);
    cxt.lineTo(0,20);
    cxt.stroke();
    cxt.closePath();

    效果如图:

    到此为止,这个时钟的图就画出来了,就这样就结束了吗?这么丑,美化一下嘛!好吧,我们把分针稍微点缀一下!

    //画出时针,分针,秒针交叉点
    cxt.beginPath();
    cxt.strokeStyle="#f00";
    cxt.arc(0,0,5,0,360,false);
    cxt.fillStyle="#fff";   //填充颜色
    cxt.fill();     //填充
    cxt.stroke();  
    cxt.closePath();
                
    //秒针装饰
    cxt.beginPath();
    cxt.strokeStyle="#f00";
    cxt.arc(0,-160,5,0,360,false);
    cxt.fill();   //填充
    cxt.stroke();
    cxt.closePath();
    cxt.restore();

    说明一下:上一段是画的3个指针交叉的地方,给点装饰,见图上,这样显得针是围绕一个点转的,fill()是填充的意思,相当于是画一个实心圆,我们填充的是白色,外面的描边是红色,你可以这么理解,一个空心圆里面填充了一个白色,懂了吧;
    下面的是分针指针尖山的一个小装饰,跟前面的是一样的,只是位置不一样,但是这样是不是更加“高端大气上档次”了;

    效果如图:

    到这里就结束了吗?好像不走耶,好吧,我们让他动起来,动起来首先要知道时间,那我们就获取一下本地的时间:

    //获取时间
    var now = new Date();     //定义时间
    var sec = now.getSeconds();  //获取秒
    var minute = now.getMinutes();   //获取分钟
    var hour = now.getHours();    //获取小时
    //小时必须获取浮点类型,产生偏移(小时+分钟比)
    hour = hour + minute/60;  
    //将24小时转换为12小时
    hour=hour>12?hour-12:hour;

    为什么要写最后2行呢?解释一下,最后一行是因为本地时间是24小时制,而我们的时钟是12小时,所以我们要转换一下,变成12小时;倒数第二行是,如果不加这行,时针只要没有满一个小时,指针一直指针整数刻度上的,而实际的钟表不是这样的,时针在不是整点的时候会有一点偏移,所以我们加的偏移量就是分针走的比例(大家有兴趣可以试一下不加会是什么效果);

    要动起来我们需要用到setInterval()函数,那我们将我们写的代码用一个函数包起来,这样就简洁了,但是不包含开始的2句,我们用drawClock()吧

    function drawClock(){
        //获取时间
        var now = new Date();   //定义时间
        var sec = now.getSeconds();  //获取秒
        var minute = now.getMinutes();  //获取分钟
        var hour = now.getHours();   //获取小时
        //小时必须获取浮点类型,产生偏移(小时+分钟比)
        hour = hour + minute/60;
        //将24小时转换为12小时
        hour=hour>12?hour-12:hour;
    
        //表盘(蓝色)
        cxt.beginPath();  //画笔开始
        cxt.lineWidth = 5;  //设置画笔的线宽
        cxt.strokeStyle="blue";  //设置画笔的颜色
        cxt.arc(250,250,200,0,360,false);  //绘制圆形,坐标250,250 半径200,整圆(0-360度),false表示顺时针
        cxt.stroke();   //绘图
        cxt.closePath();  //结束画布
        //刻度
            //时针刻度
            for(var i=0; i<12; i++){
            cxt.save();
            //设置时针的样式
                              cxt.lineWidth=7;
            cxt.strokeStyle="#000";
            //设置异次元空间原点
            cxt.translate(250,250);
            //设置旋转角度
            cxt.rotate(i*30*Math.PI/180);
            cxt.beginPath();
            cxt.moveTo(0,-170); //画线, 从坐标0,-170开始
            cxt.lineTo(0,-190); //到坐标0,-190结束
            cxt.stroke();
            cxt.closePath();
            cxt.restore();
            }
            //分针刻度
            for(var i=0; i<60;i++){
            cxt.save();
            cxt.lineWidth=5;
            cxt.strokeStyle="#000";
            cxt.translate(250,250);
            cxt.rotate(i*6*Math.PI/180);
            cxt.beginPath();
            cxt.moveTo(0,-180);
            cxt.lineTo(0,-190);
            cxt.stroke();
            cxt.closePath();
            cxt.restore();    
            }
                    
        //时针
       cxt.save();
       //时针样式
       cxt.lineWidth = 7;
       cxt.strokeStyle="#000";
       cxt.translate(250,250);
       cxt.rotate(/*hour**/30*Math.PI/180);
       cxt.beginPath();
       cxt.moveTo(0,-140);
       cxt.lineTo(0,10);
       cxt.stroke();
       cxt.closePath();
       cxt.restore();
                
       //分针
       cxt.save();
       //分针样式
       cxt.lineWidth = 5;
       cxt.strokeStyle="#000";
       cxt.translate(250,250);
       cxt.rotate(/*minute**/6*Math.PI/180);
       cxt.beginPath();
       cxt.moveTo(0,-160);
       cxt.lineTo(0,15);
       cxt.stroke();
       cxt.closePath();
       cxt.restore();
                
       //秒针
       cxt.save();
       cxt.lineWidth = 3;
       cxt.strokeStyle="#f00";
       cxt.translate(250,250);
       cxt.rotate(/*sec**/60*Math.PI/180);
       cxt.beginPath();
       cxt.moveTo(0,-185);
       cxt.lineTo(0,20);
       cxt.stroke();
       cxt.closePath();
                
       //画出时针,分针,秒针交叉点
       cxt.beginPath();
       cxt.strokeStyle="#f00";
       cxt.arc(0,0,5,0,360,false);
       cxt.fillStyle="#fff";   //填充颜色
       cxt.fill();   //填充
       cxt.stroke();
       cxt.closePath();
                
       //秒针装饰
       cxt.beginPath();
       cxt.strokeStyle="#f00";
       cxt.arc(0,-160,5,0,360,false);
       cxt.fill();
       cxt.stroke();
       cxt.closePath();
       cxt.restore();
       }
       //使用setinterval();让时钟动起来
      
       setInterval(drawClock,1000);

    ok,动起来,好,刷新,咦,没有动耶,为什么呢,原来我们的指针都只是定义了一个角度,肯定懂不起来啦,好,我们将我们获取的时间嫁到指针上

                    
                //时针
                cxt.save();
                //时针样式
                cxt.lineWidth = 7;
                cxt.strokeStyle="#000";
                cxt.translate(250,250);
                cxt.rotate(/*hour**/30*Math.PI/180);
                cxt.beginPath();
                cxt.moveTo(0,-140);
                cxt.lineTo(0,10);
                cxt.stroke();
                cxt.closePath();
                
                cxt.restore();
                
                //分针
                cxt.save();
                //分针样式
                cxt.lineWidth = 5;
                cxt.strokeStyle="#000";
                cxt.translate(250,250);
                cxt.rotate(minute*6*Math.PI/180);
                cxt.beginPath();
                cxt.moveTo(0,-160);
                cxt.lineTo(0,15);
                cxt.stroke();
                cxt.closePath();
                
                cxt.restore();
                
                //秒针
                cxt.save();
                cxt.lineWidth = 3;
                cxt.strokeStyle="#f00";
                cxt.translate(250,250);
                cxt.rotate(sec*60*Math.PI/180);
                cxt.beginPath();
                cxt.moveTo(0,-185);
                cxt.lineTo(0,20);
                cxt.stroke();
                cxt.closePath();


    看各指针旋转角度的变化,不错,被你找到了,那现在应该可以转了吧,看图

    如图所示:

    哎呀,妈妈呀,这是什么怪物,怎么会这样呢?你的是这样吗?是这样就对了,原因是每一次指针旋转都是画上去的,走一步画一步,就出现了像扇子一样的东西,所以我们要在画图之前清空画布,就是画之前清掉前面画的

    cxt.clearRect(0,0,500,500); //清除画布

    这个是什么意思呢,实际上是2个坐标,0,0  和 500,500 对应整个画布;

    那这样应该就万事大吉了吧,刷新,啧啧,总觉得哪里不对劲,对,好像出来的时候慢了点,要等一会才出来,你的是这样吗,是这样啊,是这样 就对了,因为我们在他动之前让他把表画出来,所以执行setInterval()函数时需要1秒之后才开始画,这就是为什么要等大概1秒针才出现的原因,解决方法,在setInterval()前执行drawClock()函数;

    drawClock();
    setInterval(drawClock,1000);

    到这里,所有的问题就都解决了,你的时钟动了没,现在几点了!

    现在我把整个代码附在下面,供大家参考学习:

    <!doctype html>
    <html>
        <head>
        <meta charset="utf-8">
        <title>canvas时钟</title>
        </head>
    <body>
            <canvas width="500" height="500" style="background:yellow; margin:50px auto; display:block; " id="clock">
                您的浏览器当前版本不支持canvas表签
            </canvas>
            <script>
                var clock = document.getElementById("clock");
                var cxt = clock.getContext('2d');
                
                function drawClock(){
                cxt.clearRect(0,0,500,500); //清除画布
                //获取时间
                var now = new Date();   //定义时间
                var sec = now.getSeconds();  //获取秒
                var minute = now.getMinutes();  //获取分钟
                var hour = now.getHours();   //获取小时
                //小时必须获取浮点类型,产生偏移(小时+分钟比)
                hour = hour + minute/60;
                //将24小时转换为12小时
                hour=hour>12?hour-12:hour;
    
                //表盘(蓝色)
                cxt.beginPath();  //画笔开始
                cxt.lineWidth = 5;  //设置画笔的线宽
                cxt.strokeStyle="blue";  //设置画笔的颜色
                cxt.arc(250,250,200,0,360,false);  //绘制圆形,坐标250,250 半径200,整圆(0-360度),false表示顺时针
                cxt.stroke();   //绘图
                cxt.closePath();  //结束画布
                //刻度
                    //时针刻度
                    for(var i=0; i<12; i++){
                        cxt.save();
                        //设置时针的样式
                        cxt.lineWidth=7;
                        cxt.strokeStyle="#000";
                        //设置异次元空间原点
                        cxt.translate(250,250);
                        //设置旋转角度
                        cxt.rotate(i*30*Math.PI/180);
                        cxt.beginPath();
                        cxt.moveTo(0,-170); //画线, 从坐标0,-170开始
                        cxt.lineTo(0,-190); //到坐标0,-190结束
                        cxt.stroke();
                        cxt.closePath();
                        cxt.restore();
                    }
                    //分针刻度
                    for(var i=0; i<60;i++){
                        cxt.save();
                        cxt.lineWidth=5;
                        cxt.strokeStyle="#000";
                        cxt.translate(250,250);
                        cxt.rotate(i*6*Math.PI/180);
                        cxt.beginPath();
                        cxt.moveTo(0,-180);
                        cxt.lineTo(0,-190);
                        cxt.stroke();
                        cxt.closePath();
                        cxt.restore();    
                    }
                    
                //时针
                cxt.save();
                //时针样式
                cxt.lineWidth = 7;
                cxt.strokeStyle="#000";
                cxt.translate(250,250);
                cxt.rotate(hour*30*Math.PI/180);
                cxt.beginPath();
                cxt.moveTo(0,-140);
                cxt.lineTo(0,10);
                cxt.stroke();
                cxt.closePath();
                
                cxt.restore();
                
                //分针
                cxt.save();
                //分针样式
                cxt.lineWidth = 5;
                cxt.strokeStyle="#000";
                cxt.translate(250,250);
                cxt.rotate(minute*6*Math.PI/180);
                cxt.beginPath();
                cxt.moveTo(0,-160);
                cxt.lineTo(0,15);
                cxt.stroke();
                cxt.closePath();
                
                cxt.restore();
                
                //秒针
                cxt.save();
                cxt.lineWidth = 3;
                cxt.strokeStyle="#f00";
                cxt.translate(250,250);
                cxt.rotate(sec*6*Math.PI/180);
                cxt.beginPath();
                cxt.moveTo(0,-185);
                cxt.lineTo(0,20);
                cxt.stroke();
                cxt.closePath();
                
                //画出时针,分针,秒针交叉点
                cxt.beginPath();
                cxt.strokeStyle="#f00";
                cxt.arc(0,0,5,0,360,false);
                cxt.fillStyle="#fff";   //填充颜色
                cxt.fill();   //填充
                cxt.stroke();
                cxt.closePath();
                
                //秒针装饰
                cxt.beginPath();
                cxt.strokeStyle="#f00";
                cxt.arc(0,-160,5,0,360,false);
                cxt.fill();
                cxt.stroke();
                cxt.closePath();
                cxt.restore();
            }
            //使用setinterval();让时钟动起来
            drawClock();
            setInterval(drawClock,1000);
            </script>
    </body>
    </html>


    希望对大家的学习有帮助!

      

  • 相关阅读:
    Beta 冲刺 (2/7)
    Beta 冲刺 (1/7)
    2017软件工程实践总结
    华为软件开发云评测
    android开发——用户头像
    学生&部门智能匹配程序
    学生会里学生汇
    数独棋盘生成器
    读与思
    Java接口
  • 原文地址:https://www.cnblogs.com/liugang-vip/p/3557983.html
Copyright © 2020-2023  润新知