复习Javascript到Canvas的知识点,看到一个使用Canvas绘制的静态时钟例子,便想将其变成动态显示系统时间的时钟动画。另外再配上数字显示的时钟,一个小的时钟模块的诞生了!目前的界面还比较粗糙,只有简单的界面和动画效果。

演示观看地址:http://htmlpreview.github.io/?https://github.com/omocc/Demo/blob/master/%E6%97%B6%E9%92%9Fdemo/clock.html

  这个时钟包括两个部分,动画圆盘时钟和数字时钟。首先是使用超时调用setTimeout()方法做一个循环动画的效果以显示时间。先看数字时钟的代码,比较简单,圆盘时钟的做法也是模仿数字时钟做的。

var ntimeoutId = setTimeout(ntimeOut,0);
function ntimeOut() {
clearTimeout(ntimeoutId);
var now = new Date();
var hours = now.getHours().toString(),
minutes = now.getMinutes().toString(),
seconds = now.getSeconds().toString();
var time = hours+" : "+minutes+" : "+seconds;
var timediv = document.getElementById("time");
timediv.innerHTML = time;
ntimeoutId = setTimeout(ntimeOut, 1000);
}

  1、首先是设定一个超时调用以首次调用方法来显示系统当前时间,时间之所以设置为0,是为了没有延迟地显示时间。

  2、每次循环之前清除前一次的超时调用(为什么要这样做,我也还不清楚???可能是为了内存性能相关,注释了以后程序也能正常执行。)

  3、取得当前系统时间,并按照一定的字符串格式保存。

  4、为了动态显示在页面中,在Html页面中定义了一个空的div元素,以存放该时间字符串。使用DOM操作将其添加到div元素中即可动态显示。

  5、通过不停循环超时调用,就可以动态显示数字时钟了, 同过开发者工具也可以看到div元素里的动态变化。

  接下来就是制作圆盘时钟动画,圆盘和数值的刻画都比较简单,只要使用context.arc()方法和context.fillText()方法即可。下面是其源代码:

     context.beginPath();
context.restore();
context.translate(0,0);
context.clearRect(0,0,300,300); //绘制时钟内外边框
context.arc(150,150,149,0,2 * Math.PI,false);
context.moveTo(295,150);
context.arc(150,150,145,0,2 * Math.PI,false); context.font = "bold 18px Arial";
context.textAlign = "center"; //绘制时钟表盘数值
context.fillText("12",150,25);
context.fillText("3",285,150);
context.fillText("6",150,290);
context.fillText("9",15,150);
context.fillText("1",215,45);
context.fillText("2",265,95);
context.fillText("4",265,225);
context.fillText("7",95,275);
context.fillText("5",215,275);
context.fillText("8",35,225);
context.fillText("10",35,95);
context.fillText("11",75,45); context.stroke();
context.closePath();

  接下来就是指针的绘制了,指针的绘制中参考高程中的做法,使用变换操作context.translate()方法改变原点,再绘制路径成为指针会方便很多。另一个绘制指针的难点是弧度的计算,当然这就是数学问题了。下面先看源代码:

     //绘制指针
context.save();
context.translate(150,150); //时针
context.moveTo(0,0);
hour(hours); function hour(thour) {
context.save();
var newhour = 0;
if(thour>12) {
newhour = thour-12;
} else {
newhour = thour;
}
context.rotate((2*Math.PI/12)*newhour);
context.lineTo(0,-80);
context.restore();
} //分针
context.moveTo(0,0);
minute(minutes); function minute(tminute) {
context.save();
context.rotate((2*Math.PI/12)*tminute/5);
context.lineTo(0,-110);
context.restore();
} //秒针
context.moveTo(0,0);
second(seconds); function second(tsecond) {
context.save();
context.fillStyle = "#fff";
context.rotate((2*Math.PI/12)*tsecond/5);
context.lineTo(0,-120);
context.restore();
} context.stroke();

  在绘制指针中,每种指针都使用了函数来改变每次指针绘制的弧度来实现指针转动的动画效果。对于时针,则将二十四小时制转化为十二小时制,每次转动30°即可。分针和秒针则是转为0到11进行转动,简单的数学问题,相信大家都是比我厉害的,当时我还纠结了一阵子。在每个函数中都有使用context.save()方法和context.restore()方法,是为了保存和复原初始化时的路径,不然指针都要跑偏啦。

  所有工作基本准备就绪了,接下来只要将钟盘和指针都放在超时调用中即可,但仍然有些问题需要注意的,比如说钟盘和指针的原点设置不同,要注意使用保存和复原来还原初始化时候的路径,不然钟盘和指针都要跑偏了。另外要注意的是,使用Canvas制作动画,每次的动画循环都是要清空画布重新绘制,不然指针一直转转转,转成一朵花的样子。

  完整的圆盘时钟代码如下:

//显示指针时间
var drawing = document.getElementById("drawing");
if(drawing.getContext) {
var context = drawing.getContext("2d"); var rtimeoutId = setTimeout(roudClock,0);
function roudClock() {
clearTimeout(rtimeoutId); context.beginPath();
context.restore();
context.translate(0,0);
context.clearRect(0,0,300,300); //绘制时钟内外边框
context.arc(150,150,149,0,2 * Math.PI,false);
context.moveTo(295,150);
context.arc(150,150,145,0,2 * Math.PI,false); context.font = "bold 18px Arial";
context.textAlign = "center"; //绘制时钟表盘数值
context.fillText("12",150,25);
context.fillText("3",285,150);
context.fillText("6",150,290);
context.fillText("9",15,150);
context.fillText("1",215,45);
context.fillText("2",265,95);
context.fillText("4",265,225);
context.fillText("7",95,275);
context.fillText("5",215,275);
context.fillText("8",35,225);
context.fillText("10",35,95);
context.fillText("11",75,45); context.stroke();
context.closePath(); var now = new Date();
var hours = now.getHours(),
minutes = now.getMinutes(),
seconds = now.getSeconds(); //绘制指针
context.save();
context.translate(150,150); //时针
context.moveTo(0,0);
hour(hours); function hour(thour) {
context.save();
var newhour = 0;
if(thour>12) {
newhour = thour-12;
} else {
newhour = thour;
}
context.rotate((2*Math.PI/12)*newhour);
context.lineTo(0,-80);
context.restore();
} //分针
   context.moveTo(0,0);
minute(minutes); function minute(tminute) {
context.save();
context.rotate((2*Math.PI/12)*tminute/5);
context.lineTo(0,-110);
context.restore();
} //秒针
context.moveTo(0,0);
second(seconds); function second(tsecond) {
context.save();
context.fillStyle = "#fff";
context.rotate((2*Math.PI/12)*tsecond/5);
context.lineTo(0,-120);
context.restore();
} context.stroke();
context.restore();
context.translate(0,0);
context.save();
rtimeoutId = setTimeout(roudClock,1000);
}
}

  最后总结我在这次Demo的练习中遇到的几点问题:

  1、画布重绘问题

  在指针动画循环的时候,前一个路径都没有方法清除,造成每一次循环都留下印记。尝试了小范围地使用clearRect()方法,结果发现只能在范围内清除了表盘和数字的内容,指针依然会留下痕迹。后来通过搜索,得到的答案是使用Canvas制作动画一定是要进行重绘的,在新绘制内容前要清空画布内容,每一次的动画变化都要清空一次。重绘的方法可以参考一下链接,我使用的是clearRect()方法清空整个画布。

参考方法链接:http://blog.csdn.net/u010484625/article/details/46046217

  2、save()方法和restore()方法的使用

  因为我的钟盘和指针的原点设定不同,所以在进行重绘后,钟盘的原点会改变为指针的原点,因此要利用save()方法和restore()方法改变。除了这个地方也有其他一些地方需要用到,适合操作以后改变了设定,但后续操作需要用原设定的情况。注意的是这两个方法只会保存和恢复设定,而不是内容。

  3、translate()方法的使用

  translate()方法是属于变换操作中的,可改变画布的原点,默认画布的原点在画布的左上角。使用这个方法可以更轻易地绘制指针的路径,当然还有一些其他需要用的地方,我还没有接触到。

  4、setTimeout()方法的使用

  使用超时调用是比间歇调用更好的方法,使用超时调用可以模拟间歇调用。通过在超时调用传入的函数中再添加超时调用就可以很好地模仿循环。还可以在函数中根据一些条件限定循环的次数和时间。

  5、对应当前时间,弧度的使用方法

  这就是数学问题,我在这个问题纠结了好一会儿,没有拐过弯来,明白其中的原理就不是技术上的难题了。

  6、对于时间重复取得和重复使用方法的问题

  对于代码中还存在有重复代码的情况,我还没有想到更好的方法减少冗余。例如在获取时间上,在两个超时调用中均有重复定义,但若是把他们放在全局中,则没有了动画效果,只是显示加载完成后的那个静态时间。另外的是指针的函数设定中有重复的部分,是否可以合为一个函数方法再进行调用呢。

  欢迎大家提出想法,对于不足的地方提出建议,一起来交流。

使用Canvas制作时钟动画的更多相关文章

  1. 用Canvas制作loading动画

    上一篇讲到用SVG制作loading动画,其中提到了线性渐变在扇形区域中的问题,并且用SVG SIML语法制作的loading动画并不是所有浏览器都兼容,所以现在用Canvas重新实现了一遍. 这里与 ...

  2. canvas制作简单动画

    在画布元素<canvas>中,除了绘制图形.图像.文字外,还可以制作一些简单的动画,制作过程十分简单,主要分为两步操作: 1.自定义一个函数,用于图形的移动或其他动作. 2.使用setIn ...

  3. 利用HTML5的canvas制作万花筒动画特效

    <!DOCTYPE HTML> <html> <head> <style> #canvas{ background-color:#cccccc; } & ...

  4. 15个超强悍的CSS3圆盘时钟动画赏析

    在网页上,特别是个人博客中经常会用到时钟插件,一款个性化的时钟插件不仅可以让页面显得美观,而且可以让访客看到当前的日期和时间.今天我们给大家收集了15个超强悍的圆盘时钟动画,很多都是基于CSS3,也有 ...

  5. Canvas制作的下雨动画

    简介 在codepen上看到一个Canvas做的下雨效果动画,感觉蛮有意思的.就研究了下,这里来分享下,实现技巧.效果可以见下面的链接. 霓虹雨: http://codepen.io/natewile ...

  6. 14款超时尚的HTML5时钟动画

    时钟动画在网页应用中也非常广泛,在一些个人博客中,我们经常会看到一些相当个性化的HTML5时钟动画.今天我们向大家分享了14款形态各异的超时尚HTML5时钟动画,其中有圆盘时钟.3D时钟.个性化时钟等 ...

  7. 14款形态各异的超时尚HTML5时钟动画

    14款超时尚的HTML5时钟动画(附源码)   时钟动画在网页应用中也非常广泛,在一些个人博客中,我们经常会看到一些相当个性化的HTML5时钟动画.今天我们向大家分享了14款形态各异的超时尚HTML5 ...

  8. [JS,Canvas]日历时钟

    [JS,Canvas]日历时钟 Html: <!doctype html> <html> <head> <meta charset="UTF-8&q ...

  9. 酷!使用 jQuery & Canvas 制作相机快门效果

    在今天的教程中,我们将使用 HTML5 的 Canvas 元素来创建一个简单的摄影作品集,它显示了一组精选照片与相机快门的效果.此功能会以一个简单的 jQuery 插件形式使用,你可以很容易地整合到任 ...

随机推荐

  1. JS学习二(循环)

    JS中的循环结构 [循环结构的执行步骤] 1.声明循环变量: 2.判断循环条件: 3.执行循环体操作: 4.更新循环变量: 然后,循环执行2~4,知道条件不成立.跳出循环. [while 循环] wh ...

  2. 【集美大学1411_助教博客】团队作业10——项目复审与事后分析(Beta版本)

    写在前面的话 软件工程课结束了,大家开心吗?是不是再也不用熬夜写代码了?如果这门课你真的熬夜写代码了,相信你一定有收获,如果这门课结束了你觉得是自己一个全新的开始,那么这门课的意义就实现了.团队作业全 ...

  3. 201521123072《java程序设计》第七周总结

    201521123072<java程序设计>第七周总结 标签: java 1. 本周学习总结 2. 书面作业 ArrayList代码分析 1.1 解释ArrayList的contains源 ...

  4. 201521123065 《Java程序设计》第3周学习总结

    1. 本周学习总结 2. 书面作业 Q1:代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; ...

  5. 201521123060 《Java程序设计》第3周学习总结

    1. 本周学习总结 2. 书面作业 1.代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; p ...

  6. 201521123073 《Java程序设计》第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...

  7. 201521123057 《Java程序设计》第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 1.字符流与文本文件:使用 PrintWriter(写),BufferedReader(读) ...

  8. audio标签

    实例 一段简单的 HTML 5 音频: <audio src="someaudio.wav"> 您的浏览器不支持 audio 标签. </audio> 亲自 ...

  9. CentOS克隆机器步骤,图文教程

    在上一篇文章中,主要介绍了CentOS的装机步骤,这一篇文章主要介绍如何从一台装好的CentOS克隆出另一台机器,并且配置好网络. 首先被克隆的CentOS需要关机, 右键点击被克隆的CentOS-& ...

  10. bom是什么?