时钟(一)Html5的canvas实践


placeholder image
admin 发布于:2015-07-04 00:17:16
阅读:loading

背景介绍

还记得刚工作没多久的时候,无意中翻找JDK的目录发现了大类的例子,都以swing的居多,印象深刻的包括一个嵌入网页中的applet小程序,运行起来是个时钟(clock),虽然简陋,但我觉得略高端,因为一直不知道它的原理是怎么实现的,后来一个项目上看到有同事弄了个基于flash的实现版本,让我感觉眼前一亮,呵呵。不过现在想想,还真少见JS的实现版本。最近在观看兄弟连的html5视频的时候发现讲到canvas介绍,里面还有具体实现的过程,细细观看几遍下来,感觉眼前更亮了,经过两个例子的实践,发现彻底亮了。

时钟.gif小时钟.gif

实现介绍

根据实现的效果图来简单分析一下它的具体组成部分:

1) 表盘

表盘就是一个圆,设置圆的边框、背景色

2) 小时、分钟的刻度

小时刻度一共是12个,分散围绕一圈360°,平均下来每两个小时直接相差30°;

分钟刻度一共60个,同样一周下来,每相邻的度数则为6°,需要注意的是为了避免分钟的刻度与小时的刻度重叠,可以用分钟

N %5 == 0 来判断。如上图中所有的刻度都是画N个宽度像素的线段。

3) 时针

时针也是一个线段,需要根据当前时间来旋转它的角度。

4) 分针

同时针实现,长度比时针要长一些,填充其他颜色;

5) 秒针

同时针实现,长度比时针、分针来说都要长一点,可在秒针上添加一个圆圈等来区别一下。

6) 圆的正中心位置画一个小圆圈,看起来让它把3个针给固定起来。

综上要实现一个时钟需要实现的绘图技术有:画圆、画线段、图片旋转、JS定时任务、所画图形的样式(长宽、颜色)。

顺便说一下我对图片旋转的理解,当使用canvas已经画出一个表盘之后,如果想继续画表盘上的刻度,当然这些刻度是需要旋转的,而canvas对象是在同一张图片上面会话的,如果旋转图片上某部分,那怎么行呢,所以先把图片旋转之前的绘图给保存一下,再让新画的图进行旋转,同时旋转的角度啊,相对应的参照物啊都需要指定,据说这叫异次元空间。我觉得从PS绘图的角度来讲,在一个图片中,每次新绘图行时新建一个图层,所有的操作包括旋转都只对某一个图层生效,而所有图层是存在于一张图片上的,没一个图层相对来说属于异次元空间。(就那么回事儿吧,你怎么看?)

源码实现

整个实现过程并没有图片,所以一个html文件全部搞定,详细如下:

<!DOCTYPE html>
<
html>
<
head>
    <
meta charset="utf-8">
    <
title>时钟canvas</title>
</
head>
<
body>
<
canvas id="canvas" width="500" height="500">你的浏览器不支持canvas</canvas>
<
script type="text/javascript">
   
var canvas = document.getElementById("canvas");
   
var ctx = canvas.getContext("2d");
    drowClock();
    setInterval(drowClock ,
1000);

   
function initClockTheme(){
       
//设置笔触(画笔)宽度和颜色
       
ctx.strokeStyle = "#F89600";
       
ctx.lineWidth = 7;
       
//画一个圆,半径为250px大小
       
ctx.beginPath();
       
ctx.arc(250,250,200,0,360,false);
       
ctx.stroke();
       
ctx.fillStyle = "#FEFF99";
       
ctx.fill();
       
ctx.closePath();
       
//12小时的刻度
       
ctx.strokeStyle = "black";
       
for(var i=0 ; i<12 ; i++){
           
ctx.save();
           
ctx.translate(250,250);//重置旋转点
           
//设置笔触颜色
           
ctx.rotate(i * 30 * Math.PI / 180);//旋转角度,每个小时之间为30°
           
ctx.beginPath();
           
ctx.moveTo(0,-190);
           
ctx.lineTo(0,-160);
           
ctx.stroke();
           
ctx.closePath();
           
ctx.restore();
        }
       
//60分钟的刻度
       
for(var i=0 ; i<60 ; i++){
           
//5的倍数的给排除掉,避免与小时刻度重叠(少画12次)
           
if(i % 5 == 0){
               
continue;
            }
           
ctx.save();
           
ctx.translate(250,250);
           
ctx.beginPath();
           
ctx.rotate(i * 6 * Math.PI / 180);//旋转,每分钟的刻度是
           
ctx.moveTo(0,-190);
           
ctx.lineTo(0,-180);
           
ctx.stroke();
            
ctx.closePath();
           
ctx.restore();
        }
    }

   
function drowClock(){
       
ctx.clearRect(0,0,500,500);

        initClockTheme();
       
var date = new Date();
       
var hours = date.getHours();
       
var minutes = date.getMinutes();
       
var seconds = date.getSeconds();
       
minutes = minutes + seconds/60;
       
hours = hours + minutes/60;
        drowHour(
hours);
        drowMinutes(
minutes);
        drowSeconds(
seconds);
       
//美化时钟
       
drowBeautify();
    }

   
function drowHour(hours){
       
//画时针,假设临时为390°
       
ctx.save();
       
ctx.translate(250,250);
       
ctx.lineWidth = 10;
       
ctx.strokeStyle = "#FF9900";
       
ctx.beginPath();
       
ctx.rotate(hours * 30 * Math.PI / 180);
        
ctx.moveTo(0,-110);
       
ctx.lineTo(00,15);
       
ctx.stroke();
       
ctx.closePath();
       
ctx.restore();
    }

   
//画分针
   
function drowMinutes(minutes){
       
ctx.save();
       
ctx.translate(250,250);
       
ctx.beginPath();
        
ctx.strokeStyle = "#FD3400";
       
ctx.rotate(minutes * 6 * Math.PI / 180);
       
ctx.moveTo(0,-150);
       
ctx.lineTo(00,15);
       
ctx.stroke();
       
ctx.closePath();
       
ctx.restore();
    }

   
//画秒针
   
function drowSeconds(seconds){
       
ctx.save();
       
ctx.translate(250,250);//在异次元设置的样式只会在restore前有效
       
ctx.strokeStyle = "red";
       
ctx.lineWidth = 3;
       
ctx.beginPath();
       
ctx.rotate(seconds * 6 * Math.PI / 180);
       
ctx.moveTo(0,-170);
       
ctx.lineTo(0,15);
       
ctx.stroke();
       
ctx.closePath();
       
ctx.restore();
    }

   
//美化
   
function drowBeautify(){
       
//画一个圆心,方便参考
       
ctx.beginPath();
       
ctx.strokeStyle = "#D84C29";
       
ctx.arc(250,250,4,0,360,false);
       
ctx.stroke();
       
ctx.fillStyle = "aliceblue";
       
ctx.fill();
       
ctx.closePath();
       
//给秒针上画一个红桃心

       
var seconds = new Date().getSeconds();
       
ctx.save();
       
ctx.translate(250,250);//在异次元设置的样式只会在restore前有效
       
ctx.strokeStyle = "red";
       
ctx.beginPath();
       
ctx.lineWidth = 8;
       
ctx.rotate(seconds * 6 * Math.PI / 180);
       
ctx.strokeText("" , -4 , -120);
       
ctx.stroke();
       
ctx.closePath();
       
ctx.restore();

    }
</
script>
</
body>
</
html>

说明:在线运行地址“/demo/html/canvas/clock1.html”当前系统版本不可用,可参见老版本项目中对应目录下的代码。

 点赞


 发表评论

当前回复:作者

 评论列表


留言区