iT邦幫忙

2022 iThome 鐵人賽

DAY 14
0
自我挑戰組

在30天利用HTML & CSS & JavaScript完成Side Project實作系列 第 14

Day 14 Side Project : Incrementing Counter 遞增計數器

  • 分享至 

  • xImage
  •  

今天要來做的是動態計數效果,隨著固定的時間遞增固定的數字上去,因為時間設得很短,所以視覺上看起來像是連續的,如圖中那樣!


事前準備

  1. 引入 fontAwesome 的cdn,並選擇第一個all.min.css
    https://cdnjs.com/libraries/font-awesome
    https://ithelp.ithome.com.tw/upload/images/20220920/20149362MVi9dFqqwW.png

運用知識點羅列

  • CSS
知識點 使用說明
data-* Attritube 自訂義屬性
@media 設置中斷點,這裡只有設定一個寬度的斷點
  • JS
知識點 使用說明
getAttribute() 取得自訂義的屬性
Number( ) 把字串或是陣列等轉成數字型別
Math.ceil() 將傳入的數字四捨五入
setTimeOut() 設定一個計時器去執行某個函式或是某片段的程式碼

流程講解

  • HTML
    設置三個主要容器,分別為Twitter、Youtube、Facebook,放入這三個社群媒體的icon以及說明。 要注意的是data-target 這個自訂義的屬性,我們之後要利用JS去操控它,這是要讓數字跑起來的第一步
 <!-- Twitter-->
    <div class="container">
        <i class="fa-brands fa-twitter fa-3x"></i>
        <div class="counter" data-target="12000"></div>
        <span>Twitter Followers</span>
    </div>
    <!-- Youtube-->
    <div class="container">
        <i class="fa-brands fa-youtube fa-3x"></i>
        <div class="counter" data-target="5000"></div>
        <span>Youtube Subscribers</span>
    </div>
    <!-- Facebook-->
    <div class="container">
        <i class="fa-brands fa-facebook fa-3x"></i>
        <div class="counter" data-target="7500"></div>
        <span>Facebook Fans</span>
    </div>
  • CSS
    大局配置
* {
  box-sizing: border-box;
}

body {
  background-color: rgb(116, 66, 116);
  color: #fff;
  margin: 0;
  padding: 0;
  display: flex; /*讓內容水平垂直置中*/
  justify-content: center;
  align-items: center;
  height: 100vh;
  overflow: hidden;
  margin-bottom: 40px;
}

外部容器

.container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  margin: 30px 50px;
}

數字的部分

.counter {
  font-size: 60px;
  margin-top: 10px;
}

設定中斷點

@media screen and (max-width: 768px) {
  body {
    flex-direction: column;
  }
}
  • JS
// 取得所有類別為counter的元素
let counters = document.querySelectorAll(".counter");

counters.forEach((counter) => {
  let updateCounter = () => {
    let target = Number(counter.getAttribute("data-target"));
    console.log(typeof target, target);

    let c = Number(counter.innerText);
    //上面也可寫成 let c =+counter.innerText;

    let increment = target / 200;
    // 看你想要除多少都可以,除越大的數,每次遞增的量就越少

    if (c < target) {
      counter.innerText = `${Math.ceil(c + increment)}`;
      setTimeout(updateCounter, 1); //單位:ms
    } else {
      counter.innerText = target;
    }
  };

  updateCounter();
});

getAttribute()的部分因為會回傳字串,所以我們用Number()將之轉為數字,你也可以用parsInt()或是在最前面寫上+來達成

let c = Number(counter.innerText) 是把目前畫面上的數字存放到c這個變數裡,如果c小於我們的目標數字(變數target)時,它就會每 1 毫秒去執行updateCounter()這個函式,那當c大於target時,就直接賦予target的值給c

完成圖中的數字會遞增主要是靠updateCounter()這個函式來達成,而非setTimeOut()setTimeOut() 只是讓視覺上有連續的效果,延遲了某段時間 (單位:毫秒) 後,才去執行一次指定的程式碼,其實這邊用setInterval()重新建構也是可以得到一樣的效果,不過 setInterval() 是延遲了某段時間之後,才去執行對應的程式碼,然後不斷循環,延遲誤差會稍微大一點,關於誤差的部分可以參考這篇文

附上codepen連結 https://codepen.io/hangineer/pen/rNvmbgM


補充

  1. 認識 parseInt、parseFloat 與 Number 轉換成數字的三種方法

  2. 深入理解setTimeOut 與 setInterval


summary 總結

常常看到有些網頁會有這樣的數字變化效果,這篇跟第五篇 Blurry Loading 模糊加載 有異曲同工之妙,兩個同樣都是在處理延時和定時任務,不過第五篇是使用setInterval,若有興趣可以去看看

所學不精,若有解說不夠詳盡或是錯誤歡迎指教,感激不盡!那明天見囉/images/emoticon/emoticon29.gif


參考資料

50 Projects In 50 Days - HTML, CSS & JavaScript
setTimeout 與 setInterval
setTimeout()和setInterval() 何时被调用执行


上一篇
Day 13 Side Project : Drink Water 沒事多喝水
下一篇
Day 15 Side Project : Background Slider 全景輪播圖
系列文
在30天利用HTML & CSS & JavaScript完成Side Project實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言