这是github上的一个使用原生JavaScrip编程t的挑战感觉很好玩,这个挑战是由wesbos发起的感兴趣可以去它的github上看看。
02 纯 JS、CSS 时钟
关键的要点:
时钟的形状的css获取时钟的时间时针的旋转效果涉及到的css特性:
transformtransform-origintransition-timing-functiontransitioncss部分
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%; // 相当于 right3.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);