CSS動畫篇之炫酷時鐘之時鐘牆

南城大前端發表於2022-05-08

通過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)

相關文章