这是我参与更文挑战的第4天,活动详情查看: 更文挑战
2. Js and CSS Clock
一、效果展示
这里指的是我们补充 JavaScript 代码之前的初始样式和作者完成的最终样式。
index-START.html
index-FINISHED.html
我的最终效果
二、实现
最终代码
<script>
;(function(){
const second = document.querySelector('.second-hand');
const min = document.querySelector('.min-hand');
const hour = document.querySelector('.hour-hand');
function setClock(){
let data = new Date()
let secondDeg = data.getSeconds()*6 //(360/60)
let minDeg = data.getMinutes()*6 + data.getSeconds() *6 /60 //(360/60)
let hourDeg = data.getHours()*30 + data.getHours() * 30 / 60 //(360/12)
second.style.transform = `rotate(${secondDeg}deg)`
min.style.transform = `rotate(${minDeg}deg)`
hour.style.transform = `rotate(${hourDeg}deg)`
}
// function timeoutHandler(){
// setClock()
// setTimeout(timeoutHandler,1000)
// }
// function animationHandler(){
// setClock()
// window.requestAnimationFrame(animationHandler);
// }
setClock() //初始化画面
// 计时器 setInterval setTimeout requestAnimationFrame
setInterval(setClock,1000) //设置一次 执行多次
// setTimeout(timeoutHandler,1000) //设置间隔 持续执行
// window.requestAnimationFrame(animationHandler); //处理画面更新的 setTimeout
})()
</script>
复制代码
大家可能注意到了这里的立即执行合数和昨天的相比对了一个分号。加这个分号的意义就是,如果你的整个 script 标签里只有一个立即执行函数,那么不加分号也是没有关系的;如果你的代码里边有不同的层次,比如有防抖的工具,其他封装的工具,如果你的前面没有分号的话,这样所有的方法就会连在一起,这样就可能会出错。这里写了主要起一个预防的作用。
三、总结回顾
从上面的代码中可以看出,其实我们这个功能主要做了这么几件事:
实现表盘指针样式
实现旋转效果
一秒改变一次指针的状态位置
获取实时时间
过程分解
1.首先添加了一个表盘圆心样式;
/* 表盘圆心 */
.clock-face::after{
content: "";
display: block;
width: 30px;
height: 30px;
border-radius: 50%;
position:absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
background-color: #EFEFEF;
}
复制代码
2.实现时分秒针的展示和初始位置
/* .hand {
width: 50%;
height: 6px;
background: black;
position: absolute;
top: 50%;
} */
/* 这里改变了一个作者的样式 */
.hand {
position: absolute;
width: 100%;
height: 100%;
}
/* 秒针 */
.second-hand::after{
content: "";
position: absolute;
display: block;
width: 10px;
height: 50%;
background-color: #FF0000;
left:50%;
bottom: 50%;
transform: translate(-50%,0%);
}
/* 分针 */
.min-hand::after{
content: "";
position: absolute;
display: block;
width: 12px;
height: 40%;
background-color: #EFEFEF;
left:50%;
bottom: 50%;
transform: translate(-50%,0%);
}
/* 时针 */
.hour-hand::after{
content: "";
position: absolute;
display: block;
width: 15px;
height: 30%;
background-color: #EFEFEF;
left:50%;
bottom: 50%;
transform: translate(-50%,0%);
}
复制代码
这里稍微提及一下,改了作者的样式,跟作者的有什么区别:
(1)这是原作者的效果,他的针的旋转效果就是单纯的一个指针在旋转
(2)这是改变之后的样式,旋转是以一个正方形做旋转的,这样的话定位会比较容易点,定位是定在正方形内部的。
3.JavaScript 事件处理
(1)获取三个指针对应元素
const second = document.querySelector('.second-hand');
const min = document.querySelector('.min-hand');
const hour = document.querySelector('.hour-hand');
复制代码
(2)创建 setClock 方法
① 创建 Date 对象
② 获取时分秒没个指针对应的角度
function setClock(){
let data = new Date()
let secondDeg = data.getSeconds()*6 //(360/60)
let minDeg = data.getMinutes()*6 + data.getSeconds() *6 /60 //(360/60)
let hourDeg = data.getHours()*30 + data.getHours() * 30 / 60 //(360/12)
second.style.transform = `rotate(${secondDeg}deg)`
min.style.transform = `rotate(${minDeg}deg)`
hour.style.transform = `rotate(${hourDeg}deg)`
}
复制代码
- 利用定时器自动更新时间
setInterval(setClock,1000) //设置一次 执行多次
复制代码
四、重难点
计算每个指针对应的角度
1.一开始我是这样写的,但是这样写的话,出来的效果就会使这样的,大家注意分针的转动效果。
这里的分针在秒钟执行完一圈之后,是在开始下一圈转动的时候,秒针角度增加了一分钟的角度,这样虽然实现了效果,但是无论是在视觉上,还是在实现的最终结果上,都是不太对的。
let secondDeg = data.getSeconds()*6 //(360/60)
let minDeg = data.getMinutes()*6 //(360/60)
let hourDeg = data.getHours()*30 //(360/12)
复制代码
2.严格意义上来说,分针的移动效果应该是现在这样的,注意鼠标光标下面分针的移动。
不知道大家有没有注意到,这里的分针是在秒针转动的过程中,按照转动的角度平均了这一分钟的移动,这样的移动效果才是比较正常的视觉效果。
在 Wes Bos 给出的解决方案中,时针是每一小时跳动一次,要想模拟真实的时钟,要使时针在一小时内缓慢的移动到下一个时间点。所以可以利用上分钟,计算每一分钟对时针的角度影响,将加到时针角度上即可。
//作者的方案
const hourDeg = (90 + (hour / 12) * 360 + (min / 12 / 60) * 360);
复制代码
let secondDeg = data.getSeconds()*6 //(360/60)
let minDeg = data.getMinutes()*6 + data.getSeconds() *6 /60 //(360/60)
let hourDeg = data.getHours()*30 + data.getHours() * 30 / 60 //(360/12)
复制代码
定时器
在我的最终代码里,三种定时器的使用我都使用了,最终我是用的是 setInterval,定时器 setInterval 可以每隔一段固定时间将执行操作放入执行队列,我们利用它这个特性,让其在插入页面后每一秒钟更新一次时间,实现秒针转动的效果。
1. setInterval
MDN 文档使用方法:developer.mozilla.org/zh-CN/docs/…
setInterval(setClock,1000) //设置一次 执行多次
复制代码
2. setTimeout
MDN 文档使用地址:developer.mozilla.org/zh-CN/docs/…
这里只是展示实现效果
function timeoutHandler(){
setClock()
setTimeout(timeoutHandler,1000)
}
setTimeout(timeoutHandler,1000) //设置间隔 持续执行
复制代码
3. requestAnimationFrame
window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
这里只是展示一下用法,具体的用法请查看 MDN 文档:developer.mozilla.org/zh-CN/docs/…
function animationHandler(){
setClock()
window.requestAnimationFrame(animationHandler);
}
window.requestAnimationFrame(animationHandler); //处理画面更新的 setTimeout
复制代码
今天的分享到此结束了,记得持续学习!