通過CSS製作的時鐘大家肯定看到的多了,但是像下面這樣的時鐘是不是很少見,整個時鐘是有很多個小的時鐘組合而成,每秒通過多個時鐘的動畫來切換時間,不得不說這個設計是非常的炫酷且有特色。
前言
看到這個動畫效果你有什麼思路,你會怎麼實現呢?可以先想一下你的答案,看看與本文的思路是否一致。本文既然是探討的CSS動畫,那麼介面上這麼多的時鐘是儘可能的不是真的多個時鐘,那樣操作DOM及JS的邏輯就太複雜了,也沒有和此設計理念一樣,簡潔且優美。
實現過程
HTML
當你仔細看這個動圖的時候可以看出我們可以把這整個時鐘分為5塊內容,即 2 1 : 5 8,小時和分鐘的個位數和十位數,再加中間的冒號。那麼我們的HTML程式碼可以按如下所示分為5塊區域:
<div class="display">
<div class="digit">
</div>
<div class="digit">
</div>
<div class="digit separator">
</div>
<div class="digit">
</div>
<div class="digit">
</div>
</div>
每個區域裡面都是由多個小塊組成,只需要在該區域內加上固定的元素數量。比如上面的第一個區域的數量就是24(4 * 6)個。
<div class="digit">
<div class="clock"></div>
<div class="clock"></div>
<div class="clock"></div>
...省略
<div class="clock"></div>
<div class="clock"></div>
<div class="clock"></div>
</div>
CSS
每個時鐘的兩個指標將有“before” 和“after”偽元素實現,CSS程式碼如下所示:
.clock {
border-radius: 50%;
width: 60px;
height: 60px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
position: relative;
background-color: #fff;
}
.clock:before,
.clock:after {
content: '';
display: inline-block;
height: 45%;
width: 4px;
background-color: #444;
position: absolute;
left: 50%;
top: 8%;
margin-left: -2px;
transform-origin: 2px 100%;
transition: all 10s cubic-bezier(0.5, 0, 0.5, 1);
}
最終的結果是這樣的:
其實仔細看我們的時鐘只繪製了簡單的形狀,它們只需要能夠將指標定位如下在6個位置即可:
通過增加不同的類來實現,這些類改變了偽元素圍繞其各自的旋轉角度。
.clock.pos2:before {
transform: rotate(180deg);
}
.clock.pos2:after {
transform: rotate(90deg);
}
JS
現在一切都準備好了,就差怎麼顯示正確的數字,需要顯示的數字就0-9,那麼只需定義一個長度為10的陣列,陣列的每一項則對應上時鐘的位置,以此類推,子陣列的長度則是24位,對應上面提到的24個子時鐘,子陣列的內容基於上面提到的,只會有1-6的情況,0是預設的顯示樣式。整體設定數字的程式碼如下:
function setNumber(group, number) {
var clocks = group.children;
var numbers = [
'266352355555555551451664',
'263013500550055024131664',
'266316352645526451631664',
'266316352645163526451664',
'232355555145163500550014',
'266352645163163526451664',
'266352645163523551451664',
'266316350055005500550014',
'266352355145523551451664',
'266352355145163500550014'
]
for(var i = 0; i < 24; i++) {
clocks[i].classList.value = 'clock pos' + numbers[number][i]
}
}
在程式初始化的時候獲取當前時間,四個位置分別呼叫四次setNumber方法即可顯示當前的時間。
function writeTime() {
var now = new Date();
var hour = now.getHours().toString();
var minute = now.getMinutes().toString();
var number = pad(hour,2) + pad(minute, 2);
setNumber(groups[0], number[0]);
setNumber(groups[1], number[1]);
setNumber(groups[3], number[2]);
setNumber(groups[4], number[3]);
}
再加上每一分鐘的定時更新資料的邏輯,我們的時鐘動畫就運動起來啦。
function runEveryMinute(f) {
var now = new Date();
var timeUntilNextMinute = 60000 - (now.getSeconds() * 1000 + now.getMilliseconds());
setTimeout(function(){
f();
setInterval(f, 60000);
}, timeUntilNextMinute);
}
裡面還有對於個位數補0的情況,以及中間冒號的初始化沒有詳細說明,有興趣的可以看原始碼瞭解。
總結
到此整體的動畫就實現完了,和你最開始的想法有什麼區別呢,你是否有更好的想法可以評論區留言討論。如果覺得有用,如果覺得有用,點贊,關注,收藏起來,說不定哪天就用上啦~
連結
the-making-of-cooper-hewitt-clock-wall
專注前端開發,分享前端相關技術乾貨,公眾號:南城大前端(ID: nanchengfe)