iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 2
0

02 - JS and CSS Clock

俗話說的好,一天一蘋果,醫生遠離我

一天一 JS,What the f*ck JavaScript?

small steps every day - 記錄著新手村日記

CSS+JS Clock 完成目標

時鐘一開始就提供了一個鐘面,也寫好了三支指針

  • 功能

    • 顯示目前的時間並可以更新時針、分針、秒針
  • 畫面

    • 讀得到目前的時間

    • 指針要能分辨長短

    • 分針、時針的特性

index_START.html

html 的整體結構如下所示, class="clock" 包住 class="clock-face",內部又有 hand hour-hand hand min-handhand second-hand 三個 div ,分別代表秒針、分針、時針

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>JS + CSS Clock</title>
</head>
<body>
    <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=5);
      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%;
    }
  </style>

  <script>
  </script>
</body>
</html>

CSS - step by step

<style>
    html {
      background: #018DED url(http://unsplash.it/1500/1000?image=881&blur=5);
      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);
    }

	.clock-face:after {
      content: '';
      display: block;
      width: 30px;
      height: 30px;
      position: absolute;
      background-color: #fff;
      border-radius: 100%;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }

    .hand {
      position: absolute;
      width: 100%;
      height: 100%;
    }

    .second-hand:after {
      content: '';
      position: absolute;
      display: block;
      width: 5px;
      height: 50%;
      background-color: #f00;
      left: 50%;
      bottom: 50%;
      transform: translate(-50%, 0%);
    }

    .min-hand:after {
      content: '';
      position: absolute;
      display: block;
      width: 10px;
      height: 40%;
      background-color: white;
      left: 50%;
      bottom: 50%;
      transform: translate(-50%, 0%);
    }

    .hour-hand:after {
      content: '';
      position: absolute;
      display: block;
      width: 15px;
      height: 25%;
      background-color: white;
      left: 50%;
      bottom: 50%;
      transform: translate(-50%, 0%);
    }
</style>

JS - step by step

首先,先分別抓到秒針、分針、時針的 class 指定給變數 second、min、hour,在後方的計算時間時需要將三個針旋轉角度,達到時鐘的效果

<script>
  const second = document.querySelector('.second-hand')
  const min = document.querySelector('.min-hand')
  const hour = document.querySelector('.hour-hand')
</script>

可以使用 new Date() 來抓到現在的時間

Date():https://ubin.io/WvAtZC

<script>
  const second = document.querySelector('.second-hand')
  const min = document.querySelector('.min-hand')
  const hour = document.querySelector('.hour-hand')
  
	function setClock(){
  	let data = new Date()
  	console.log(data) 
    // Sat Sep 14 2019 23:28:44 GMT+0800 (台北標準時間)
  }

  setClock()
</script>

算出一秒鐘、一分鐘、一小時中秒針、分針、時針需要轉動多少角度,一圈轉360度時,秒針、分針動一秒為6度、時針為30度,知道這件事情後,我們才能將三者指定為變數(但有小瑕疵稍後會解決)

Date.prototype.getSeconds():https://ubin.io/Uw21Ep
Date.prototype.Minutes():https://ubin.io/L6mcH5
Date.prototype.getHours():https://ubin.io/2DvLNS

<script>
    const second = document.querySelector('.second-hand')
    const min = document.querySelector('.min-hand')
    const hour = document.querySelector('.hour-hand')

    function setClock(){
      let data = new Date()

      let secondDeg = data.getSeconds() * 6 // (deg = 360/60)
      let minDeg = data.getMinutes() * 6 // (deg = 360/60)
      let hourDeg = data.getHours() * 30 // (deg = 360/12)
    }
    
    setClock()
 </script>

透過 event.style.transform 更動秒針、分針、時針的 CSS,要它們轉動個字的角度

Style transform Property:https://ubin.io/1LyRPt

<script>
    const second = document.querySelector('.second-hand')
    const min = document.querySelector('.min-hand')
    const hour = document.querySelector('.hour-hand')

    function setClock(){
      let data = new Date()

      let secondDeg = data.getSeconds() * 6 // (deg = 360/60)
      let minDeg = data.getMinutes() * 6 // (deg = 360/60)
      let hourDeg = data.getHours() * 30 // (deg = 360/12)

      second.style.transform = `rotate(${secondDeg}deg)`
      min.style.transform = `rotate(${minDeg}deg)`
      hour.style.transform = `rotate(${hourDeg}deg)`

    }
    setClock()
</script>

透過 setInterval() 不斷在間隔固定的時間重複執行:程式碼中的 1000 代表每隔一秒就會呼叫一次函式 setClock

setTimeout() / setInterval():https://reurl.cc/Qp76ab

<script>
    const second = document.querySelector('.second-hand')
    const min = document.querySelector('.min-hand')
    const hour = document.querySelector('.hour-hand')

    function setClock(){
      let data = new Date()

      let secondDeg = data.getSeconds() * 6 // (deg = 360/60)
      let minDeg = data.getMinutes() * 6 // (deg = 360/60)
      let hourDeg = data.getHours() * 30 // (deg = 360/12)

      second.style.transform = `rotate(${secondDeg}deg)`
      min.style.transform = `rotate(${minDeg}deg)`
      hour.style.transform = `rotate(${hourDeg}deg)`

    }
    setClock()
    setInterval(setClock,1000) 
</script>

還有一點小瑕疵...你會發現分針、時針不太符合常態,會真正到等分針、秒針轉完一圈才進位一大格,但應該是會慢慢的趨向於進一格,因此在抓角度的算式必須更動一下,可以試著畫圖想想看...

<script>
    // 上略
    function setClock(){
      let data = new Date()

      let secondDeg = data.getSeconds() * 6 
      let minDeg = data.getMinutes() * 6 + data.getSeconds() * 6 / 60
      // 1min = 6deg / 60sec * secondDeg
      let hourDeg = data.getHours() * 30 + data.getMinutes() * 30 / 60
      // 1hr = 30deg / 60min * minDeg

      second.style.transform = `rotate(${secondDeg}deg)`
      min.style.transform = `rotate(${minDeg}deg)`
      hour.style.transform = `rotate(${hourDeg}deg)`

    }
    setClock()
    setInterval(setClock,1000)

</script>

就大功告成啦!

JS - Final

<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>

本刊同步於個人網站:http://chestertang.site/
本次範例程式碼原作者來源:https://reurl.cc/zybW5k


上一篇
新手村01 - JavaScript Drum Kit
下一篇
新手村03 - CSS Variables
系列文
新手村-30 Day JS Coding Challenge30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言