使用Canvas制作时钟动画
复习Javascript到Canvas的知识点,看到一个使用Canvas绘制的静态时钟例子,便想将其变成动态显示系统时间的时钟动画。另外再配上数字显示的时钟,一个小的时钟模块的诞生了!目前的界面还比较粗糙,只有简单的界面和动画效果。
这个时钟包括两个部分,动画圆盘时钟和数字时钟。首先是使用超时调用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制作时钟动画的更多相关文章
- 用Canvas制作loading动画
上一篇讲到用SVG制作loading动画,其中提到了线性渐变在扇形区域中的问题,并且用SVG SIML语法制作的loading动画并不是所有浏览器都兼容,所以现在用Canvas重新实现了一遍. 这里与 ...
- canvas制作简单动画
在画布元素<canvas>中,除了绘制图形.图像.文字外,还可以制作一些简单的动画,制作过程十分简单,主要分为两步操作: 1.自定义一个函数,用于图形的移动或其他动作. 2.使用setIn ...
- 利用HTML5的canvas制作万花筒动画特效
<!DOCTYPE HTML> <html> <head> <style> #canvas{ background-color:#cccccc; } & ...
- 15个超强悍的CSS3圆盘时钟动画赏析
在网页上,特别是个人博客中经常会用到时钟插件,一款个性化的时钟插件不仅可以让页面显得美观,而且可以让访客看到当前的日期和时间.今天我们给大家收集了15个超强悍的圆盘时钟动画,很多都是基于CSS3,也有 ...
- Canvas制作的下雨动画
简介 在codepen上看到一个Canvas做的下雨效果动画,感觉蛮有意思的.就研究了下,这里来分享下,实现技巧.效果可以见下面的链接. 霓虹雨: http://codepen.io/natewile ...
- 14款超时尚的HTML5时钟动画
时钟动画在网页应用中也非常广泛,在一些个人博客中,我们经常会看到一些相当个性化的HTML5时钟动画.今天我们向大家分享了14款形态各异的超时尚HTML5时钟动画,其中有圆盘时钟.3D时钟.个性化时钟等 ...
- 14款形态各异的超时尚HTML5时钟动画
14款超时尚的HTML5时钟动画(附源码) 时钟动画在网页应用中也非常广泛,在一些个人博客中,我们经常会看到一些相当个性化的HTML5时钟动画.今天我们向大家分享了14款形态各异的超时尚HTML5 ...
- [JS,Canvas]日历时钟
[JS,Canvas]日历时钟 Html: <!doctype html> <html> <head> <meta charset="UTF-8&q ...
- 酷!使用 jQuery & Canvas 制作相机快门效果
在今天的教程中,我们将使用 HTML5 的 Canvas 元素来创建一个简单的摄影作品集,它显示了一组精选照片与相机快门的效果.此功能会以一个简单的 jQuery 插件形式使用,你可以很容易地整合到任 ...
随机推荐
- 如何解决xshell中无法输入中文的问题
自从安上了xshell以后,用着那叫一个顺手,美中不足的就是一直无法输入中文.不过,既然学习IT,就要习惯英文嘛~直到--我遇到了脚本,写好一个脚本,必要的注释是少不了的,但是作为一个英文渣渣,我真的 ...
- 深度剖析Java变量栈&对象堆
Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...
- Python中os和shutil模块实用方法集锦
Python中os和shutil模块实用方法集锦 类型:转载 时间:2014-05-13 这篇文章主要介绍了Python中os和shutil模块实用方法集锦,需要的朋友可以参考下 复制代码代码如下: ...
- 对eigrp默认网络的理解!
EIGRP 默认网络设置的个人总结 (了解即可) //该机制同rip和ospf的default-informationoriginate,原理相同,只是配置格式不同. //!!(唯一作用)该命令起到减 ...
- 集美大学网络1413第九次作业成绩(团队五) -- 测试与发布(Alpha版本)
NO.NE团队的项目链接有效,六个核桃和六指神功团队可以请教下他们,避免因IP地址无效或者因tomcat不打开就不能访问的情况,毕竟助教没办法知道此时此刻它是开着还是关闭啊啊啊... 题目 团队作业5 ...
- 【Beta阶段】第六次scrum meeting
Coding/OSChina 地址 1. 会议内容 学号 主要负责的方向 昨日任务 昨日任务完成进度 接下去要做 99 PM 着手联网功能 100% 配合100完成联网功能 100 DEV 完善服务器 ...
- sublime text 按下Ctrl + B 显示空白的解决办法
环境:windows xp , sublime text 2 条件:环境变量也已经设置好,可是无论怎么编译都是空白,如图: 于是鄙人百度之,发现不少网友都有这样的问题,但是网上给出的的解决方案千篇一律 ...
- 06jQuery-04-DOM操作
jQuery既然是为了帮助你能从js的繁琐中解脱出来,自然在DOM操作上也有自己的一套. 1.修改Text和HTML 之前我们提到过,如果用JS的话,你要修改Text或者HTML需要用到其innerH ...
- JPA继承方式
在JPA中,实体继承关系的映射策略共有三种:单表继承策略(SINGLE_TABLE).Joined策略和Table_PER_Class策略. 1.单表继承策略 单表继承策略,父类实体和子类实体共用一张 ...
- 关于linux下的文件权限
在ls指令加 -l 参数能看到文件权限 就像这样: drwxrwxr-x 2 asml users 4096 Jul 24 02:45 desktop 第一个d表示这是个目录,若为"-&qu ...