使用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 插件形式使用,你可以很容易地整合到任 ...
随机推荐
- web程序员标准环境之DreamWeaver【推荐】
Adobe Dreamweaver,简称"DW",中文名称 "梦想编织者",是美国MACROMEDIA公司开发的集网页制作和管理网站于一身的所见即所得网页编辑器 ...
- JS学习一
js中的变量输出 [使用JS的三种方式] 1. 在HTML标签中,直接内嵌JS(并不提倡使用): <button onclick="alert('你真点啊!')"> ...
- 团队作业9--测试与发布(Beta版)
Beta版本测试报告 1.在测试过程中总共发现了多少Bug?每个类别的Bug分别为多少个? a. 修复的bug: 写入SD存储卡文件权限问题 页面正确跳转 及 部分页面闪退的问题 b. 不能重现的bu ...
- 团队作业8——第二次项目冲刺(Beta阶段) 5.19
Day1--5.19 1.展开站立式会议(拍摄者:武健男): 会议内容:(1)新成员自我介绍,使大家能更快熟悉并一起合作. (2)由于我们之前的项目经理去了别的小组,所以我们投票选取新成员林乔桦作为我 ...
- 201521123011《Java程序设计》第5周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 参考资料: 百度脑图 XMind 2. 书面作业 作业参考文件下载 1.代码阅读:Child压缩包内源代码 1.1 com.p ...
- 201521123037 《Java程序设计》第2周学习总结
1. 本周学习总结 初步学会分析使用命令提示符进行编译的命令 了解使用import引入不同包的类 学会码云与eclipse的连接 使用Array和String函数编写程序 2. 书面作业 1. 使用E ...
- Java课程设计——象棋(201521123042 姚佳希)
1. 团队课程设计博客链接 Java课程设计(团队版) 2 个人负责模块或任务说明 ChessBoard类创建棋盘及界面. ChessPoint类创建棋盘格点及界面. ChessPiece类创建棋子及 ...
- Java:双括号初始化 /匿名内部类初始化法
偶然见到一种初始化方式,感到十分新奇: //新建一个列表并赋初值A.B.C ArrayList<String> list = new ArrayList<String>() { ...
- [LeetCode]Count and Say 计数和发言
Count and Say 计数和发言 思路:首先要理解题意,可以发现后者是在前者的基础之上进行的操作,所以我们拿之前的结果作为现在函数的参数循环n-1次即可,接下来就是统计字符串中相应字符的个数,需 ...
- bookStore第二篇【图书模块、前台页面】
图书模块 分析 在设计图书管理的时候,我们应该想到:图书和分类是有关系的.一个分类可以对应多本图书. 为什么要这样设计?这样更加人性化,用户在购买书籍的时候,用户能够查看相关分类后的图书,而不是全部图 ...