JS30 Day 2 筆記


Posted by GL on 2023-05-23

功能

製作一個實時的時鐘

Demo

step 1 : 設置時針、分針、秒針的 CSS 樣式

.hand {
  width: 50%;
  height: 6px;
  background: black;
  position: absolute;
  top: 50%;

  // 改變軸心點 transform-origin:x,y,設為 100% 後(或用 right),讓指針的軸心改在最右邊
  transform-origin: 100%;
  // 旋轉元素,正值為順時針旋轉,負值為逆時針旋轉
  transform: rotate(90deg);
  transition: all 0.05s linear;
  // 指針末端修尖
  border-radius: 30% 0 0 30%;
}

.hour-hand {
  height: 10px;
  margin-top: -5px;
  transform-origin: 100%;
  transition: all 1s linear;
}

.second-hand {
  background-color: red;
  // 調整動畫轉場效果貝茲曲線:cubic-bezier
  transition: all 0.05s cubic-bezier(0.25, 0.1, 0.84, 2.82); 
}

step 2 :JS 取得當前時間,以及與時鐘上對應的角度

  • 分針、秒針每一格走的角度: 360 度 / 60(分、秒) = 6 度
  • 時針每一格走的角度: 360 度 / 12(小時) = 30 度

細節處理: 由於時針與分針會因為時間的推移,慢慢前往下一格,不是一次就跳到下一格,所以把這個也考慮進去後角度才精準

  • 秒針角度: (當前秒數 / 60 秒)* 360 度
  • 分針角度: (當前分鐘 / 60 分) 360 度 + (當前秒數 / 60 秒) 6 (每格 6 度)
  • 時針角度: (當前小時 / 12 小時) 360 度 + (當前分鐘 / 60 分) 30 (每格 30 度)
function setClock(){
  let now = new Date()
  let second = now.getSeconds()
  let secondDegrees = ((second / 60) * 360) + 90
  secondHand.style.transform = `rotate(${secondDegrees}deg)`

  let minute = now.getMinutes()
  let minusDegrees = (minute / 60) * 360 + (minute / 60) * 6 + 90
  minuteHand.style.transform = `rotate(${minusDegrees}deg)`

  let hour = now.getHours()
  let hoursDegrees = (hour / 12) * 360 + (hour/ 60) * 30 + 90
  hourHand.style.transform = `rotate(${hoursDegrees}deg) scaleX(0.7)`
}
}

step 3 :JS 設定定時器,每秒重複執行一次

// 用 setInterval 方法,設定固定間隔,重複執行一次
  setInterval(setClock, 1000);


  // 用 setTimeout 方法,設定多少時間後,執行一次,想要持續執行的話,要在 function 裡再 setTimeout 呼叫自己
  // function handleTimeout() {
  //   setClock();
  //   setTimeout(handleTimeout, 1000);
  // }
  // setTimeout(handleTimeout, 1000);


  // 用 window.requestAnimationFrame 方法,畫面更新,跟 setTimeout 一樣,要重複執行的話需在 function 裡呼叫自己
  // function handleTimeAnimation() {
  //   setClock();
  //   window.requestAnimationFrame(handleTimeAnimation)
  // }
  // window.requestAnimationFrame(handleTimeAnimation);

Javascript

1. 用 element.style.<styleAttribute> 改變 CSS 效果:

const hourHand = document.querySelector('.hour-hand');
hourHand.style.transform = `rotate(${hoursDegrees}deg) scaleX(0.7)`;

2. setInterval、setTimeout、window.requestAnimationFrame 的區別

  • setInterval(): 固定一段時間,重複執行 function(例如:時鐘、輪播)
// 第一個參數是要執行的 function,第二個參數固定多久時間(毫秒)執行
setInterval(callback, time)
  • setTimeout():設定延遲時間,只執行一次
// 第一個參數是要執行的 function,第二個參數延遲的多長時間(毫秒)後執行
setInterval(callback, time)
  • window.requestAnimationFrame():
    處理畫面的更新,類似 setTimeout() 只會執行一次,重複執行時要在 function 內呼叫自己,如果用 canvas 動畫,為了處理畫面流暢度,建議可使用 window.requestAnimationFrame
// 第一個參數是要執行的 function,第二個參數延遲的多長時間(毫秒)後執行
window.requestAnimationFrame(callback)

延伸

秒針回到 0 秒時會閃一下,參考 Reference 提供的解決方法

當將指針為 90 度時,將 transition 屬性移除

if (secondDegrees === 90) secondHand.style.transition = 'all 0s'
else secondHand.style.transition = 'all 0.05s';

if (minusDegrees === 90) minuteHand.style.transition = 'all 0s'
else minuteHand.style.transition = 'all 0.1s'

參考資料:


#JS 30







Related Posts

[13] 值 - 字串

[13] 值 - 字串

程式導師實驗計畫 Week8 作業與解答

程式導師實驗計畫 Week8 作業與解答

 Week1 筆記|[GIT101]  GIT 學習筆記

Week1 筆記|[GIT101] GIT 學習筆記


Comments