canvas 时钟 -- 效果图
一、先来简单介绍画时钟需要的 canvas 知识
1. 在 html 页面中添加 canvas 元素,必须定义 canvas 元素的 id 属性值以便接下来的调用。
HTML 代码:
- <canvas id="canvas" class="canvas" width="400" height="400" border:>
- </canvas>
2. 使用 id 寻找 canvas 元素,在 js 代码中使用 document.getElementById() 等方法获取 id。
- var canvas = document.getElementById("canvas");
3. 通过 canvas 元素的 getContext 方法来获取其上下文(Context), 即创建 Context 对象,以获取允许绘画的 2D 环境。
- var ctx = canvas.getContext("2d");
4. 先来认识一下 canvas 的绘制方法。
(1)绘制矩形的两种方法:fillRect 和 strokeRect
前者用于绘制用颜色填充(fill)区域的矩形,后者用于绘制轮廊(stroke)或线条。图形指定颜色用到了两个属性,即 fillStyle 和 strokeStyle,前者用于指定要绘制的填充区域的颜色,后者用于指定要绘制的线条颜色。
- //绘制填充颜色矩形,默认黑色
- ctx.fillStyle="red";
- ctx.fillRect(0,0,200,100);
- //绘制有颜色线条
- ctx.strokeStyle="blue";
- ctx.strokeRect(0,0,100,50);
(2)绘制圆形
绘制圆形是会用到四种方法:beginPath、arc、closePath 和 fill 或 stroke。
- //画圆填充红颜色
- //绘制园用法:ctx.arc(x,y,radius,startAngle,endAngle,anticlockwise);
- ctx.beginPath();
- ctx.fillStyle="red";
- ctx.arc(0,0,100,0,2*Math.PI,true);
- ctx.closePath();
- ctx.fill();
- //线条蓝色画圆
- ctx.beginPath();
- ctx.strokeStyle="blue";
- ctx.lineWidth=10;//设置线条宽度
- ctx.arc(0,0,174,0,Math.PI*2,true);
- ctx.stroke();
(3)绘制直线
用到两个主要方法:moveTo 和 lineTo 以及 stroke。
ctx.moveTo(x,y)——规定线起始点 (x,y)。ctx.lineTo(x,y)——规定直线路线的终点。
- ctx.moveTo(0, 0);
- ctx.lineTo(200, 100);
- ctx.stroke(); //该方法用于沿该路径绘制线条
二、画 canvas 时钟过程
首先,定义画布字体的为圆角,让我们看起来美美的:ctx.lineCap="round";
其次,非常重要,时钟是随着时分秒针的转动而转动的,so——我们需要画布范围内必须设计画布不断清除和刷新:ctx.clearRect(0,0,400,400);
再次,一个画布初始中心点(0,0)是在画布左上角,so——画时钟需要把中心点转移:ctx.translate(200,200);
最后,也是最重要的,每多一个 save() 保存就必须在下面补上一个还原 restore();
1、画分刻线
画线嘛,上面咱们已经讲过画线的步骤,就不多说啦!只需要注意用到 rotate() 方法将,先用 ctx.moveTo(),ctx.lineTo 在画布右侧画出第一根分刻线,再定义需要旋转的角度变量——rotateD, 经过 ctx.rotate(rotateD) 方法来 for 循环以及画布不断清除刷新的状态,即可画出分刻线。
当然这里还需要注意一点:画布需要用到另个方法来包含要执行的内容,分别是 save()、restore()。save() 方法把当前状态的一份拷贝压入到一个保存图像状态的栈中。这就允许你临时地改变图像状态,然后,通过调用 来恢复以前的值。我打个比喻:我有一只手,戴上手套去完成一些事情,手套摘下来之后,我的手还是我的手。额,有点。。。呵呵
- //画刻度线
- for (var i = 0; i < 60; i++) {
- ctx.save();
- ctx.beginPath();
- var rotateD = i*Math.PI*2/60;
- ctx.rotate(rotateD);
- ctx.lineWidth = 4;
- ctx.moveTo(170,0);
- ctx.lineTo(160,0);
- ctx.stroke();
- ctx.restore();
- };
2、画时刻线
同理,画时刻线只需要修改线宽以及旋转角度
3、画时针
在前面 new 一个 data 变量 var date = new Date;,并且定义一个时针随时间变化旋转角度也变化的变量 rotateH。
小时针旋转角度 rotateH;
公式:rotateH = 时针旋转角度 + 分针旋转角度 / 12 - 直角 = data.getHours()/12*2*Math.PI + date.getMinutes()/60/12*Math.PI*2 - Math.PI/2;
(为什么会减 Math.PI/2 呢,因为时针的初始值为(-12,0)、(125,0);针指向正好是在三点中位置,所以需要减掉一个直角才能从十二点开始旋转)。
4、画分针
定义一个分针随时间变化旋转角度也变化的变量 rotateM。
公式:rotateM = 分针旋转角度 + 秒针旋转角度 / 60 - 直角 = date.getMinutes()/60*Math.PI*2 + date.getSeconds()/60/60*Math.PI*2 - Math.PI/2;
5、画秒针
定义一个分针随时间变化旋转角度也变化的变量 rotateS。
公式:rotateM = 秒针旋转角度 - 减直角 = date.getSeconds()/60*Math.PI*2 - Math.PI/2;
6、时针数字略
三、canvas 实现时钟完整代码
js 完整代码:
- jQuery(function($){
- function clock(){
- var canvas= document.getElementById("canvas");
- var ctx = canvas.getContext("2d");
- var date = new Date;
- ctx.lineCap = "round";//字体变圆角
- ctx.clearRect(0,0,400,400);//不断清除画布 不断再执行刷新
- ctx.save();//每多一个保存就必须在下面补上一个还原restore()
- ctx.translate(200, 200);//中心点转移
- //画刻度线
- for (var i = 0; i < 60; i++) {
- ctx.save();
- ctx.beginPath();
- var rotateD = i*Math.PI*2/60;
- ctx.rotate(rotateD);
- ctx.lineWidth = 4;
- ctx.moveTo(170,0);
- ctx.lineTo(160,0);
- ctx.stroke();
- ctx.restore();
- };
- for (var i = 0; i < 12; i++) {
- ctx.save();
- ctx.beginPath();
- var rotateB = i*Math.PI*2/12;
- ctx.lineWidth = 6;
- ctx.rotate(rotateB);
- ctx.moveTo(170,0);
- ctx.lineTo(150,0);
- ctx.stroke();
- ctx.restore();
- };
- //画时针
- var rotateH = date.getHours()/12*Math.PI*2 + date.getMinutes()/60/12*Math.PI*2 - Math.PI/2;
- ctx.save();
- ctx.beginPath();
- ctx.rotate(rotateH);
- ctx.lineWidth=12;
- ctx.moveTo(-12,0);
- ctx.lineTo(125,0);
- ctx.stroke();
- ctx.restore();
- //画分针
- var rotateM = date.getMinutes()/60*Math.PI*2 + date.getSeconds()/60/60*Math.PI*2 - Math.PI/2;
- ctx.save();
- ctx.strokeStyle="red";
- ctx.beginPath();
- ctx.rotate(rotateM);
- ctx.lineWidth=9;
- ctx.moveTo(-12,0);
- ctx.lineTo(135,0);
- ctx.stroke();
- ctx.restore();
- //画秒针
- var rotateS = date.getSeconds()/60*Math.PI*2 - Math.PI/2;
- ctx.save();
- ctx.strokeStyle="red";
- ctx.beginPath();
- ctx.rotate(rotateS);
- ctx.lineWidth=6;
- ctx.moveTo(-16,0);
- ctx.lineTo(140,0);
- ctx.stroke();
- //画中心圆点
- ctx.fillStyle="red";
- ctx.arc(0,0,10,0,2*Math.PI)
- ctx.closePath();
- ctx.fill();
- //画秒针圆圈头
- ctx.strokeStyle="red";
- ctx.moveTo(160,0);
- ctx.arc(150,0,8,0,2*Math.PI);
- ctx.stroke();
- ctx.restore();
- // 画clock的表盘
- ctx.beginPath();
- ctx.strokeStyle="blue";
- ctx.lineWidth=10;
- ctx.arc(0,0,174,0,Math.PI*2);
- ctx.stroke();
- ctx.restore();
- window.requestAnimationFrame(clock);
- };
- window.requestAnimationFrame(clock);
- });
来源: http://www.cnblogs.com/beyond-utf-8/p/beyond-utf-8.html