
这天是越来越冷了,人也越发的懒起来,早上起来简直要老命,下班回去也只想进被子里面,游戏都不想打了╮(﹀_﹀)╭,冷呀。。。。
好了,写个时钟来激励一下懒惰的自己吧。
旋转方式
做时钟首先要把样式给搞定,主要是围绕中心旋转的样式。
围绕中心旋转形成等分状态其实有两种做法,假设html样式如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14
 | <ul class="pox">     <li>1</li>     <li>2</li>     <li>3</li>     <li>4</li>     <li>5</li>     <li>6</li>     <li>7</li>     <li>8</li>     <li>9</li>     <li>10</li>     <li>11</li>     <li>12</li> </ul>
 | 
- 让li全部定位到pox中心,用css3的旋转rotate让其围绕中心旋转角度,再配合translate偏移,给它一个x轴的偏移量,就变成了围绕中心旋转的样式了: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 | .box ul{     width: 200px;     height: 200px;     border-radius: 50%;     border:1px solid red;     position: relative;     display: inline-block;     margin: 100px; } .box li{     width: 50px;     height:50px;     border:1px solid red;     border-radius: 50%;     line-height: 48px;     text-align: center;     position: absolute;     top: 50%;     left:50%;     margin: -25px 0 0 -25px;     transform-origin:50% 50%; } var lists = document.querySelectorAll(".box .pox li"); for(var i=0;i<lists.length;i++){     lists[i].style.cssText = `transform: rotate(${i*30}deg) translate(98px, -50%);`; }
 |  
 
-  当然这种旋转非常的简单,但是也有一定的缺陷的,其缺点是文字什么的也一起旋转了,时钟的数字可不能一起旋转了,所以这刻度线什么的用这个简单方便,但是数字得用另一种方式。 
- 好了万能的数学该来了,用sin和cos实现,我们把父元素所占的空间当成一个坐标轴,其宽的一半当成半径画个圆,如 r = 父元素.offsetHeight/2,其中心坐标点就是(r,r),| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 | <ul class="pox2">     <li>1</li>     <li>2</li>     <li>3</li>     <li>4</li>     <li>5</li>     <li>6</li>     <li>7</li>     <li>8</li>     <li>9</li>     <li>10</li>     <li>11</li>     <li>12</li> </ul> var lists2 = document.querySelectorAll(".box .pox2 li"); for(var j=0;j<lists2.length;j++){     var r = lists2[0].parentNode.offsetHeight/2,     angle = j*30/180*Math.PI;     x = r + r*Math.cos(angle);     y = r + r*Math.sin(angle);     lists2[j].style.cssText = `top:${y}px;left:${x}px;`; }
 |  
 

其实理解起来也不难,先得到每个li的弧度值,然后根据三角函数计算出li的在坐标轴中的坐标,x轴的坐标为r+r*cosθ,y轴的坐标为r+r*sinθ,这里有点小知识,js的象限是顺时针开始的,初始0度是从时钟的三点方向开始的,和数学的是反着来的,当然你可能不理解,我的图也有点挫,应该画右下角的,你把右下角当成第一象限来理解要好一点,自己画一遍就什么都有了。
好了,准备就绪,开始画时钟了,html结构如下。
| 1 2 3 4 5 6 7 8 9 10 11 12
 |  <div class="clock">     <ul class="line-min"></ul>     <ul class="line-hour">     </ul>     <ol class="number"></ol>     <ul class="pointer">         <li class="hour"></li>         <li class="min"></li>         <li class="sec"></li>         <li class="circle"></li>     </ul> </div>
 | 
初始表盘css:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
 | *{ 	margin: 0; 	padding: 0; } ol,ul { 	margin: 0; 	padding: 0; 	list-style: none; } .clock { 	position: relative; 	width: 200px; 	height: 200px; 	border-radius: 100%; 	background-color: #292a38; 	margin: 50px auto; } .pointer li.circle { 	position: absolute; 	top: 50%; 	left: 50%; 	transform-origin: left center; 	background: #fff; 	width: 10px; 	height: 10px; 	border-radius: 100%; 	margin-top: -5px; 	margin-left: -5px; } .pointer li { 	position: absolute; 	top: 50%; 	left: 50%; 	transform-origin: left center; 	background: #fff; } .pointer li.hour { 	width: 45px; 	height: 3px; 	margin-top: -1px; } .pointer li.min { 	width: 60px; 	height: 2px; 	margin-top: -1px; } .pointer li.sec { 	width: 80px; 	height: 1px; 	margin-top: -1px; }
 | 
.line-min是分刻度线,.line-hour是小时刻度线,.number是1-12的时间数字,.hour是时针,.min分针,.sec秒针,.circle中心圆点。
这次我们用ES6的class来写吧,先定义一个Time类,后面的方法都是写在Time类里面的,Time里面的构造方法constructor调用初始化函数init,init就先空着吧。
| 1 2 3 4 5 6 7 8
 | var time = class Time{     constructor(){ 		this.init(); 	}     init(){     } }
 | 
为了写得方便点,我们先建立两个工具函数,addcss函数是向传入的dom中添加css样式,getclass是根据传入的css获取dom节点:
| 1 2 3 4 5 6
 | addcss(obj,mycss){     obj.style.cssText = mycss; } getclass(cls){ 	return document.querySelector(cls); }
 | 
我们先来画时钟刻度线,用第一种旋转方式:
| 1 2 3 4 5 6 7 8
 | drawLines(wrap, total, translateX){			     var gap = 360/total;     for(var i=0;i<total;i++){         var li = document.createElement('li');         this.addcss(li,`transform:rotate(${i*gap}deg) translate(${translateX}px,-50%)`);         wrap.append(li);     } }
 | 
补上刻度css
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
 | .line-hour li, .line-min li { 	position: absolute; 	left: 50%; 	top: 50%; 	transform-origin: left center; 	background-color: #fff; } .line-hour li { 	width: 10px; 	height: 2px; } .line-min li { 	width: 5px; 	height: 2px; }
 | 
我们用drawLines函数绘制刻度线,分别传入wrap(父节点),total(时钟的刻度个数,时针12个,分针是60个),translateX(第一种旋转方式x轴的偏移量),这个函数生成了刻度线li,并且添加css样式后放到了传入的父节点中。
然后我们再绘制时钟数字,当然数字可不能旋转,所以得用第二种旋转方式:
由于初始度数是0,刚好是3点,所以3对应的弧度应该是0,6点是π/2,9点是π,12点是3π/2,通过传入的数字得到其对应的弧度如下:
| 1 2 3 4 5 6 7 8 9 10
 |     时钟            角度     弧度      sin          cos // 3:x:2r,y:r; 	     0	     0       sin 0        cos 1 // 6:x:r,y:2r;	     90	    π/2      sin 1        cos 0 // 9:x:0,y:r;	     180     π       sin 0        cos -1 // 12:x:r,y:0;	     270    3π/2     sin -1       cos 0 我们把弧度全部除以π得到 // 3   0;	=   3-3 = 0/6			(num-3)/6 * π // 6   1/2;	=   6-3 = 3/6 // 9   1;	=   9-3 = 6/6 // 12  3/2;	=   12-3 = 9/6
 | 
我们可以推算出公式为(num-3)/6 * π,故弧度为 = (i-3)/6*Math.PI;
| 1 2 3 4 5 6 7 8 9 10 11
 | drawNumbers(wrap){							     var r = wrap.offsetHeight/2;     var child = '';     for(var i=1;i<=12;i++){         var  angle = (i-3)/6*Math.PI;         var myX = r + r*Math.cos(angle),           myY = r + r*Math.sin(angle);              child+=`<li style="left:${myX}px;top:${myY}px;">${i}</li>`;     }     wrap.innerHTML = child; }
 | 
数字css
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
 | .number { 	position: absolute; 	height: 140px; 	width: 140px; 	left: 50%; 	top: 50%; 	transform: translate(-50%, -50%); 	font-family: 'Microsoft Yahei'; 	font-size: 15px; 	color: #fff; } .number li { 	position: absolute; 	transform: translate(-50%, -50%); }
 | 
这样数字函数也完成了,接下来我们在init初始化函数里面调用,new time(),让其生成出来:
| 1 2 3 4 5 6
 | init(){     this.drawLines(this.getclass('.line-min'), 60, 85);     this.drawLines(this.getclass('.line-hour'), 12, 80);     this.drawNumbers(this.getclass('.number')); } new time();
 | 
我们就得到了时钟的大致样式了,只是时钟的针还不会走:

最后我们写个move函数让时钟开始走动
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
 | move(){     var h = this.getclass('.hour'),     m = this.getclass('.min'),     s = this.getclass('.sec');     setInterval(function(){         var now = new Date(),         hour = now.getHours(),         min = now.getMinutes(),            sec = now.getSeconds();         var hangle = 30*hour + 0.5*min -90,         mangle = 6*min + 0.1*sec -90,         sangle = 6*sec -90;         this.addcss(h,`transform:rotate(${hangle}deg)`);         this.addcss(m,`transform:rotate(${mangle}deg)`);         this.addcss(s,`transform:rotate(${sangle}deg)`);     }.bind(this),1000); }
 | 
其余的可能没啥问题,只有指针的角度计算这里可能要说一下,
小时是12个小时,所以1个小时=360°/12=30°,当然还要加上分钟的偏移,一个小时60分钟,60分钟就要偏移30°,所以1分钟为0.5°,故小时=30*小时+0.5*分钟,当然也可以计算秒的,但是太小了(1/120),这里就忽略不计了,分针和秒针同上。由于初始位置是3点那里,以3点为基准,故3点旋转角度为0°,1点为-60°,6点为90°,故所有角度应该减去90°再进行旋转。init()里面调用:
| 1 2 3 4 5 6
 | init(){     this.drawLines(this.getclass('.line-min'), 60, 85);     this.drawLines(this.getclass('.line-hour'), 12, 80);     this.drawNumbers(this.getclass('.number'));     this.move(); }
 | 
ok,一个简单的时钟就完成了。
本文代码地址:链接