做者:©liyuechun
簡介:JavaScript30 是 Wes Bos 推出的一個 30 天挑戰。項目免費提供了 30 個視頻教程、30 個挑戰的起始文檔和 30 個挑戰解決方案源代碼。目的是幫助人們用純 JavaScript 來寫東西,不借助框架和庫,也不使用編譯器和引用。如今你看到的是這系列指南的第 2 篇。完整指南在 從零到壹全棧部落。javascript
次日的練習是用JS+CSS模擬時鐘效果。css
效果以下:html
實現以上模擬時鐘的效果,大體思路和解決方案以下:java
分別獲取到當前時間的時、分、秒。git
經過時分秒對一圈360度,進行映射,肯定每個指針所需旋轉的角度。github
經過CSS的transform:rotate(deg)
,來實時的調整指針在鍵盤中的位置。微信
<div class="clock"> <div class="clock-face"> <div class="hand hour-hand"></div> <div class="hand min-hand"></div> <div class="hand second-hand"></div> </div> </div>
<style> html { background: #018DED url(http://unsplash.it/1500/1000?image=881&blur=50); background-size: cover; font-family: 'helvetica neue'; text-align: center; font-size: 10px; } body { margin: 0; font-size: 2rem; display: flex; flex: 1; min-height: 100vh; align-items: center; } .clock { width: 30rem; height: 30rem; border: 20px solid white; border-radius: 50%; margin: 50px auto; position: relative; padding: 2rem; box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.1), inset 0 0 0 3px #EFEFEF, inset 0 0 10px black, 0 0 10px rgba(0, 0, 0, 0.2); } .clock-face { position: relative; width: 100%; height: 100%; transform: translateY(-3px); /* account for the height of the clock hands */ } .hand { width: 50%; height: 6px; background: black; position: absolute; top: 50%; transform-origin: 100%; transform: rotate(90deg); transition: all 0.05s; transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1); } </style>
涉及到的特性:框架
transform-oragin
函數
調整指針的初始位置以及旋轉的軸點:transform-oragin佈局
transform-oragin: 100%; //初始化使三個指針所有指向12時
transform: rotate()
設置旋轉角度
transition
transition: all //0.05s;設置動畫時間爲0.05秒
transition-timing-function: cubic-bezier(x, x, x, x)
設置 transition-time-function
的值,以實現秒針「滴答滴答」的效果。此外注意 transform
中的 rotate
(旋轉)屬性由角度來控制,能夠試着在頁面上修改這個參數來查看效果。
<script> const secondHand = document.querySelector('.second-hand'); const minsHand = document.querySelector('.min-hand'); const hourHand = document.querySelector('.hour-hand'); function setDate() { const now = new Date(); const seconds = now.getSeconds(); const secondsDegrees = ((seconds / 60) * 360) + 90; secondHand.style.transform = `rotate(${secondsDegrees}deg)`; const mins = now.getMinutes(); const minsDegrees = ((mins / 60) * 360) + ((seconds / 60) * 6) + 90; minsHand.style.transform = `rotate(${minsDegrees}deg)`; const hour = now.getHours(); const hourDegrees = ((hour / 12) * 360) + ((mins / 60) * 30) + 90; hourHand.style.transform = `rotate(${hourDegrees}deg)`; } setInterval(setDate, 1000); setDate(); </script>
獲取秒針、分鐘、小時節點
const secondHand = document.querySelector('.second-hand'); const minsHand = document.querySelector('.min-hand'); const hourHand = document.querySelector('.hour-hand');
獲取當前時間秒、分、小時
const now = new Date(); const seconds = now.getSeconds(); const mins = now.getMinutes(); const hour = now.getHours();
計算秒、分、小時角度
const secondsDegrees = ((seconds / 60) * 360) + 90; const minsDegrees = ((mins / 60) * 360) + ((seconds / 60) * 6) + 90; const hourDegrees = ((hour / 12) * 360) + ((mins / 60) * 30) + 90;
根據角度設置樣式
secondHand.style.transform = `rotate(${secondsDegrees}deg)`; minsHand.style.transform = `rotate(${minsDegrees}deg)`; hourHand.style.transform = `rotate(${hourDegrees}deg)`;
設置定時器,每秒調用一次setDate
函數
setInterval(setDate, 1000);
此處存在一個小瑕疵,當秒針旋轉一圈以後回到初始位置,開始第二圈旋轉,角度值的變化時 444° → 90° → 96° .... 這個過程當中,指針會先逆時針從 444° 旋轉至 90°,再繼續咱們指望的順時針旋轉,因爲秒針變換時間只有 0.05s,因此呈現的效果就是秒針閃了一下,若是想要觀察細節,能夠將 .second
設爲 transition: all 1s
,效果以下所示:
要解決這個問題,目前找到了兩種解決辦法:
第一種
<script> 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(); </script>
第二種
<script> const secondHand = document.querySelector('.second-hand'); const minsHand = document.querySelector('.min-hand'); const hourHand = document.querySelector('.hour-hand'); let secondDeg = 0; let minDeg = 0; let hourDeg = 0; function initDate() { const date = new Date(); const second = date.getSeconds(); secondDeg = 90 + (second / 60) * 360; const min = date.getMinutes(); minDeg = 90 + (min / 60) * 360 + ((second / 60) / 60) * 360; const hour = date.getHours(); hourDeg = 90 + (hour / 12) * 360 + ((min / 60) / 12) * 360 + (((second / 60) / 60) / 12) * 360; } function updateDate() { secondDeg += (1 / 60) * 360; minDeg += ((1 / 60) / 60) * 360; hourDeg += (((1 / 60) / 60) / 12); secondHand.style.transform = `rotate(${ secondDeg }deg)`; minsHand.style.transform = `rotate(${ minDeg }deg)`; hourHand.style.transform = `rotate(${ hourDeg }deg)`; } initDate(); setInterval(updateDate, 1000); </script>
既然引起問題的是角度的大小變化,那就能夠對這個值進行處理。此前的代碼中,每秒都會從新 new 一個 Date 對象,用來計算角度值,但若是讓這個角度值一直保持增加,也就不會出現逆時針迴旋的問題了。
社羣品牌:從零到壹全棧部落
定位:尋找共好,共同窗習,持續輸出全棧技術社羣
業界榮譽:IT界的邏輯思惟
文化:輸出是最好的學習方式
官方公衆號:全棧部落
社羣發起人:春哥(從零到壹創始人,交流微信:liyc1215)
技術交流社區:全棧部落BBS
全棧部落完整系列教程:全棧部落完整電子書學習筆記
關注全棧部落官方公衆號,每晚十點接收系列原創技術推送 |
---|
![]() |