时钟(一)Html5的canvas实践
admin 发布于:2015-07-04 00:17:16
阅读:loading
还记得刚工作没多久的时候,无意中翻找JDK的目录发现了大类的例子,都以swing的居多,印象深刻的包括一个嵌入网页中的applet小程序,运行起来是个时钟(clock),虽然简陋,但我觉得略高端,因为一直不知道它的原理是怎么实现的,后来一个项目上看到有同事弄了个基于flash的实现版本,让我感觉眼前一亮,呵呵。不过现在想想,还真少见JS的实现版本。最近在观看兄弟连的html5视频的时候发现讲到canvas介绍,里面还有具体实现的过程,细细观看几遍下来,感觉眼前更亮了,经过两个例子的实践,发现彻底亮了。
根据实现的效果图来简单分析一下它的具体组成部分:
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);//旋转6°,每分钟的刻度是6°
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){
//画时针,假设临时为3点90°
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”当前系统版本不可用,可参见老版本项目中对应目录下的代码。
点赞