这是github上的一个使用原生JavaScrip编程t的挑战感觉很好玩,这个挑战是由wesbos发起的感兴趣可以去它的github上看看。
02 纯 JS、CSS 时钟
关键的要点:
- 时钟的形状的css
- 获取时钟的时间
- 时针的旋转效果
涉及到的css特性:
- transform
- transform-origin
- transition-timing-function
- transition
css部分
- transform属性可以使给定元素旋转,缩放,倾斜或平移。
.clock-face {
position: relative;
width: 100%;
height: 100%;
// 给定元素沿y轴平移-3个像素
transform: translateY(-3px); /* account for the height of the clock hands */
}
transform: rotate(90deg); //旋转正90度
2.transform-origin:调整指针的初始位置以及旋转的轴点 (通俗一点就是元素以此点为轴心运动)有三个参数分别代表x、y、z轴。
transform-origin: 100%; // 相当于 right
3.transition-timing-function:用来模拟指针跳动
transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1); // cubic-bezier:三次贝塞尔曲线函数(如果感兴趣可自行查询)
4.transition:指针跳动时候的过渡效果
transition: all .1s;
因为原css样式分针、秒针、时针的长度都是一样的所以我对其进行了一点小修改
.hour-hand {
left: 108px;
width: 20%;
}
left的值就是父元素的50%减去自身的长度。如果觉得时针样式不好看也可以
border-top-left-radius: 50px; border-bottom-left-radius: 50px;
增加它的圆角。
js部分
这个部分的内容其实比较少,通过const now = new Date();
获取当前时间。
获取当前是多少秒,将秒分成六十份,每秒是六度。分针和时针的方式大同小异。
const seconds = now.getSeconds();
const secondsDegrees = ((seconds / 60) * 360) + 90;
secondHand.style.transform = `rotate(${secondsDegrees}deg)`;
这里面其实还有一个问题,就是每当秒针转一圈之后,在转第二圈时会出现掉帧情况,先是回到450度然后转到90度,由于设置的过渡过程时间比较短肉眼看不出来,可以将
transition: all 1s;
设置为一秒。针对这种情况其实有两种方法,第一种是在转了一圈之后在第二圈之前将transition去除,然后在第二圈是在将其恢复。
const secHand = document.querySelector('.second-hand');
const minHand = document.querySelector('.min-hand');
const hourHand = document.querySelector('.hour-hand');
function setDate() {
const date = new Date();
const second = date.getSeconds();
const secondDeg = (90 + (second / 60) * 360);
const min = date.getMinutes();
const minDeg = (90 + (min / 60) * 360);
const hour = date.getHours();
const hourDeg = (90 + (hour / 12) * 360 + (min / 12 / 60) * 360); // 加入分钟所占的时间,使时针可以缓慢地移动
//解决指针跳顿问题【第一种方法】
//在发生跳顿的角度值处,将 CSS 的 `transition` 属性去掉
if (secondDeg === 90) {
secHand.style.transition = 'all 0s';
} else {
secHand.style.transition = 'all 0.05s';
}
if (minDeg === 90) {
minHand.style.transition = 'all 0s';
} else {
minHand.style.transition = 'all 0.1s';
}
secHand.style.transform = `rotate(${ secondDeg }deg)`;
minHand.style.transform = `rotate(${ minDeg }deg)`;
hourHand.style.transform = `rotate(${ hourDeg }deg)`;
}
setInterval(setDate, 1000);
setDate();
第二种方法先设置一个初始值记录当前的时间,然后在创建一个函数,每隔一秒调用一次增加固定的角度,这样就只调用了一次Date()之后的是对其进行累加避免了之前的那种情况。代码如下:
function initTime() {
let time = new Date()
const seconds = time.getSeconds();
secondDeg = (seconds/60)*360 + 90;
const min = time.getMinutes();
minDeg = ((min/60)*360 + ((seconds/60)/60)*360) + 90;
const hour = time.getHours();
hourDeg = ((hour/60)*360 + (min/12/60)*360 + (((seconds/60)/60)/12)*360) + 90;
}
function updateTime() {
secondDeg += (1/60)*360;
minDeg += ((1 / 60) / 60) * 360;
hourDeg += (((1 / 60) / 60) / 12)*360;
SecondHand.style.transform = `rotate(${secondDeg}deg)`;
MinHand.style.transform = `rotate(${minDeg}deg)`;
HourdHand.style.transform = `rotate(${hourDeg}deg)`;
}
initTime();
setInterval(updateTime, 1000);