如何制作一个时钟呢。这里的时钟指的是,带有指针的那种,而不是电子的。方法至少有2种(因为目前只实践了这两种),css3和canvas

##基础数学知识

我们观察一下时钟,首先想到的是与角度有关。再有是,秒针,分针,时针之间的进位关系。
在讲解这两点之前,先考大家一个问题,4点15时,分针与时针之间的夹角是多少呢?(这可是鹅厂某年的面试题之一)

  1. 我们都知道1s = 1 / 60min,1min = 1 / 60h;
  2. 观察任意一款手表或时钟,我们会发现,通常时钟的表盘会被分成12个大格,5*12=60个小格,而整个表盘是360°,也就是说每个小格是。换句话说,秒针和分针每动一下,都会走过1小格,走过了,而时针动一下,则走过了一大格,5*6°=30°;因此,秒针和分针移动的基值是6°,时针是30°;
  3. 另外在分针走动的时候,时针也不是静止不动的,而是不甘寂寞的默默向前移动,也就是说当分针动一下,走了6°时,时针实际上也挪动了1 / 60 * 30°。所以,计算时针角度时不要忽略了分针对其的影响。(虽然秒针对分针也有着同样的影响,但几乎看不出来,所以,通常我们会将其忽略)

##如何用JS取到当前的秒,分,时

我们制作的时针是基于当前时间,而用角度的形式将其表现出来的,所以取得当前时间是首步

  • 获得当前时间,var date = new Date(),获得当前时间,以毫秒数表示。
  • getFullYear(),4位年份
  • getMonth(),从0-11,分别表示1-12月
  • getDate(),月份中的天数
  • getDay(),从0-6,分别表示星期日-星期六
  • getHours(),0-23
  • getMinutes(),0-59
  • getSecond(),0-59

##确定各指针的角度

综上两个知识点,我们可以将各指针的角度表示为:

1
2
3
4
sdegree = nSeconds * 6 - 90;
mdegree = nMinutes * 6 - 90;
hdegree = (nHour%12) * 30 + Math.floor((nMinutes/60)*30) - 90;
-90,是因为rotateZ角度旋转规则,默认是从水平开始,逆时针为+,顺时针为-)

##各指针之间的进位关系

如果还要显示此时此刻时钟的数字,那么就会面临另一个难点,临界情况,如,从2014-12-13 12:38:59-->2014-12-13 12:39:002014-12-13 12:59:59-->2014-12-13 13:00:00,2014-12-13 23:59:59-->2014-12-14 00:00:00的情况

1
2
3
4
5
6
7
8
9
10
11
if(minute != origMinute){
text(doms.minute,minute);
if(minute == "00" && hour != origHour){
text(doms.hour,hour);
if(hour == "00" && day != origDay){
text(doms.day,day);
// 根据显示文案的不同,如果有必要,重新获取本地的年,月,日
text(doms.date,zeroFill(date.getMonth()+1)+"月"+zeroFill(date.getDate())+"日");
}
}
}

##涉及到的CSS3知识点

  1. transform:rotateZ()

    只需要注意1点:rotateZ(弧度),单位是弧度,即将我们计算的角度通过公式1° = 180° / π转化

  2. transform-origin

    transform-origin:left center;,设定指针的旋转点为最左端,否则,指针将围绕着自己的中点,进行自旋转。

  3. transform: translateZ

    制作表盘中的格格,这些格格是采用绝对定位,都挤在表盘的中间,这时用tranform:translateX(75px)让它们离中心远一点,到表盘边缘去。

css3时钟北京时间纽约时间

##涉及到的canvas知识点

由于canvas自身的技术特点,在实现上与css3略有不同。

  1. 每一秒钟,当前的时钟都不是前一秒的时钟,而是一个新绘制成的时钟。各指针都是重新绘制的。

  2. 也就是时钟状态改变的时候,都需要擦除画布,绘制指针

  3. canvas也有与css3中transform类似的方法,如rotate,translate,transform,scale等

canvas时钟

##校正时间

通常,我们会使用一个定时器(每秒调用一次函数)来让指针动起来。但是当在移动端时,系统处于节约资源的考虑,当屏幕暗下去时,会禁用一些资源,这个定时器就不会工作了。当我们再次点亮屏幕时,发现时间还是停留在上一次关闭屏幕时的状态,只有当再次刷新页面时,时间也会恢复成准确时间。这时,我们可以通过设定另一个定时器的方法来校正时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// localNow:打开页面时的本地时间
// now: 打开页面时的系统时间
// clocker.date: 使用第一个定时器计算的时间
setInterval(function(e){
var localRange = (+new Date) - localNow,
actualRange = (+clocker.date) - (+now);
if(Math.abs(localRange - actualRange)/1000 > 10){
var date = new Date();
date.setTime(+now + localRange);
clocker.setDate(date).stop().start(callback);
doms.tip.style.visibility = "visible";
doms.info.style.visibility = "hidden";
setTimeout(function(){
doms.tip.style.visibility = "hidden";
doms.info.style.visibility = "visible";
},1000);
}
},500);

##参考的文章