【JS30 挑戰】 Day2 - JS and CSS Clock

這個專案練習了 CSS 轉場效果( transition & transform ),並利用 JavaScript function 來帶動 transform 的變化。

JavaScript30 是一個由 Wes Bos 提出的免費教學計畫。藉由每天完成一個小專案,練習基礎 JavaScript 。整個計畫為期30天。除了會提供教學影片外,也會先做好前期準備(例如: HTML/CSS 等相關建置),練習時只需專注於撰寫 JavaScript 部分的程式碼即可。

目標

  1. 取得當地時間當下的時/分/秒資訊。
  2. 利用取得的時間資訊,套入 CSS 設定來讓時鐘的指針移動。

練習內容

  • JavaScript
    DOM querySelector 、 function 、Date() 、setInterval()
  • CSS
    transform 、 transform-origin 、transition

開始前的準備

這部分已由教學計畫提供。

做好 HTML/CSS 設定:
做出時鐘長相並為指針做好相關設置。
為了練習 transform-origin ,指針預設往9點鐘方向。但我為了方便,已自行調整成12點鐘方向。

練習開始

1. 調整指針起點至12點鐘方向

  • 原本教學是用 transform: rotate(90deg) 處理,但為了方便,我直接調整 CSS。
  • transform-origin 跟著調整成 bottom。
  • transition 讓所有對象都執行變化,每次用0.05秒完成變化。
  • 各別設定指針外觀,以便觀察後續變化。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    .hand {
    position: absolute;
    left: 50%;
    transform-origin: bottom;
    transform: rotate(0deg);
    transition: all 0.05s;
    border-radius: 50%;
    }

    .hour-hand {
    top: 15%;
    width: 6px;
    height: 35%;
    background: tomato;
    }

    .min-hand {
    width: 4px;
    height: 50%;
    background: yellow;
    }

    .second-hand {
    width: 2px;
    height: 50%;
    background: black;
    }

2. 用 setInterval() 設定 function 執行週期。

  • 以每1000毫秒執行一次 setTime() function(秒針跳動頻率)。
    註: 1秒 = 1000毫秒
    1
    setInterval(setTime, 1000)

3. 取得時間資訊

  • 分別找出 3 支指針。
    1
    2
    3
    const hourHand = document.querySelector('.hour-hand')
    const minuteHand = document.querySelector('.min-hand')
    const secondHand = document.querySelector('.second-hand')
  • 建立一個 setTime() function ,並把要執行的動作放入函式。
  • 取得當下時間,並分別取出時/分/秒。
    1
    2
    3
    4
    5
    6
    7
    function setTime() {
    const now = new Date()

    const hours = now.getHours()
    const mins = now.getMinutes()
    const seconds = now.getSeconds()
    }
  • 依照時間比例算出旋轉角度,並帶入 CSS 的 rotate() 設置。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function setTime() {
    // 取得時間
    const now = new Date()
    const seconds = now.getSeconds();
    const mins = now.getMinutes();
    const hour = now.getHours();
    // 計算角度
    const secondsDegree = (seconds / 60) * 360;
    const minsDegree = ((mins / 60) * 360) + ((seconds / 60 / 60) * 360);
    const hourDegree = ((hour / 12) * 360) + ((mins / 12 / 60) * 360);
    // 角度代入 CSS
    secondHand.style.transform = `rotate(${secondsDegree}deg)`;
    minuteHand.style.transform = `rotate(${minsDegree}deg)`;
    hourHand.style.transform = `rotate(${hourDegree}deg)`;
    }
    到這裡就是一個會動的正確時鐘了。

4. 旋轉優化

  • 觀察秒針活動軌跡發現,當它要從 59 秒跳回 0 秒時會逆時針旋轉。因為對電腦來說 59 –> 0 是”後退”不是”前進”。最簡單的方法就是,當指針要回到 0 秒時,花費 0 秒直接變化,肉眼就看不出回退過程了。
  • 設置一個檢查:如果任一指針角度為0,transition 改為 ‘all 0s’。
    1
    2
    3
    4
    5
    6
    7
    8
    // 設置一個分辨角度的 function
    if (secondsDegree === 0
    || minsDegree === 0
    || hourDegree === 0) {
    document.querySelector('.hand').style.transition = 'all 0s'
    } else {
    document.querySelector('.hand').style.transition = 'all 5ms'
    }
  • 因為 JavaScript 有由上而下的執行順序,所以要把這段插到 “角度代入 CSS” 之前。


到這裡就全部完成了!
學習到方便的時間取得辦法後,我就要把部落格 footer 從網路上照抄的程式碼改掉了。學到的東西能確實應用真的會很有動力!

文章內容如有錯誤,歡迎留言討論!


本 Blog 上的所有文章除特别聲明外,均採用 CC BY-SA 4.0 協議 ,轉載請註明出處!