YiDaoJ's Blog

JavaScript30 - 02 JS and CSS Clock

该练习来自Wes BosJavascript30的项目,旨在三十天内每天进行一个JavaScript练习。该项目的完整文档和答案地址:JavaScript30-Github
本文是自己在练习过程中的思路小节。欢迎交流。

在线演示 中可以查看完整代码。


思路

  • 获取当前时间的时、分、秒;
  • 为指针的旋转设置动画效果;
    • transition
  • 获取单位时间内每个指针的转动度数,以及如何通过修改CSS实现指针转动的动画效果;
    • (second / 60 ) 360) , (minute / 60 ) 360) , (hour/ 12 ) * 360) ,
    • transform: rotate(xdeg)
  • 每隔单位时间重复实现指针转动效果。
    • setInterval(function, xxxms)

具体实现

CSS - 指针转动效果

1
2
3
4
5
6
7
8
9
10
11
.hand {
width:50%;
height:6px;
background:black;
position: absolute;
top:50%;
transform-origin: 100%;
transform: rotate(90deg);
transition: all .3s;
transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
}
  • transform-origin属性用于设置以哪个点为轴来旋转,100%表示以最右/下端为轴,同理0则表示以最左/上端为轴旋转。
  • 如下图所示,指针默认指向水平方向,为了符合初始位置指向0点的垂直方向,需要设置transform: rotate(90deg);

  • transition: all .3s; 设置了指针转动时的过渡效果(和效果所用时间)。
  • transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1); 设定了指针转动效果发生的速度和样式。

获取指针元素以及当前时间的时、分、秒

1
2
3
4
5
6
7
8
9
10
// 指针元素
const secondHand = document.querySelector('.second-hand');
const minHand = document.querySelector('.min-hand');
const hourHand = document.querySelector('.hour-hand');
// 当前时间的秒、分、时
const now = new Date();
const second = now.getSeconds();
const minute = now.getMinutes();
const hour = now.getHours();

更新指针所处位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 秒针
const secondDegree = ((second / 60 ) * 360) + 90;
// ((second / 60 ) * 360) 是秒数所对应的实际角度数,
// 加上90度的原始在于,在CSS中为了将指针指向初始垂直位置,
// 利用transform: rotate(90deg)进行了90度顺时针旋转,所以这里也要补上。
secondHand.style.transform = `rotate(${secondDegree}deg)`;
// 利用transform属性对指针元素进行相应度数的旋转
// 分针、时针同理
const minDegree = ((minute / 60 ) * 360 ) + 90;
minHand.style.transform = `rotate(${minDegree}deg)`;
const hourDegree = ((hour / 12 ) * 360 ) + ((minute / 60 ) * 30 ) + 90;
hourHand.style.transform = `rotate(${hourDegree}deg)`;

重复实现指针转动效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const secondHand = document.querySelector('.second-hand')
const minHand = document.querySelector('.min-hand')
const hourHand = document.querySelector('.hour-hand')
function setTime() {
const now = new Date();
const second = now.getSeconds();
const minute = now.getMinutes();
const hour = now.getHours();
const secondDegree = ((second / 60 ) * 360) + 90;
secondHand.style.transform = `rotate(${secondDegree}deg)`;
const minDegree = ((minute / 60 ) * 360 ) + 90;
minHand.style.transform = `rotate(${minDegree}deg)`;
const hourDegree = ((hour / 12 ) * 360 ) + ((minute / 60 ) * 30 ) + 90;
hourHand.style.transform = `rotate(${hourDegree}deg)`;
}
// 利用setInterval方法,每隔一秒钟调用一次setTime。
setInterval(setTime, 1000);

其他

到这里仍存在一个小问题,秒针指向12时的垂直方向时,此时其度数为(444°),继续转动时为90°、96°….,秒针会在90°时先转一圈再继续往下走,如图所示。

为了解决这个问题,可以在指针为90°时取消动画的过渡效果。

1
2
3
4
5
6
7
8
9
10
const secondDegree = ((second / 60 ) * 360) + 90;
if (secondDegree === 90)
// 如果指针度数为90°,那么取消此时的动画效果,即transition的发生时间为0。
secondHand.style.transition = 'all 0s';
else
// 其他情况下,动画效果照常发生。
secondHand.style.transition = 'all .3s';
secondHand.style.transform = `rotate(${secondDegree}deg)`;
// 分针亦同理