iT邦幫忙

2022 iThome 鐵人賽

DAY 28
0

29 - Countdown Timer

tags: JavaScript30

專案簡介

第二十九天要實作的專案是一個計時器網頁,可以讓使用者選擇要倒數的時間

課程影片:JS30 29
導讀影片:Alex

初始文件

Github 檔案位置:29 - Countdown Timer

網站的樣子

可以先看看最後的成果

正式製作

第一步一樣是先選取好要操作的元素並加上監聽,接下來我們先實作倒數計時器的函式

const timerDisplay = document.querySelector('.display__time-left');
const endTime = document.querySelector('.display__end-time');
const buttons = document.querySelectorAll('[data-time]');

function timer(seconds) {
}

function startTimer() {
}

buttons.forEach(button => button.addEventListener('click', startTimer));

這裡以之前學過的 Date 獲取目前時間,加上要倒數的時間算出最後時間後,利用 setInterval 做每 1000 毫秒一次的倒數

備註:Date.now 取出時間的單位為毫秒,因此在 then 中要先將秒數乘上 1000
備註:setInterval 會回傳定時器編號給 countdown,以便後續做清除定時器,避免有多個定時器重複運行

let countdown;

function timer(seconds) {
  clearInterval(countdown);
  const now = Date.now();
  const then = now + seconds * 1000;

  countdown = setInterval(() => {
    const secondsLeft = Math.round((then - Date.now()) / 1000);
    // check if we should stop it!
    if(secondsLeft < 0) {
      clearInterval(countdown);
      return;
    }
    console.log(secondsLeft);
  }, 1000);
}

function startTimer() {
  const seconds = parseInt(this.dataset.time);
  timer(seconds);
}


再來要實做的就是將資料渲染至畫面上了,要渲染的是每秒的即時時間倒數,以及最後倒數完的時間

我們要在一開始時就顯示最後停止時間,以及倒數的總時長,隨後就是跟著定時器每秒更新剩餘倒數時長即可

const timerDisplay = document.querySelector('.display__time-left');
const endTime = document.querySelector('.display__end-time');

function timer(seconds) {
  // ...
  const now = Date.now();
  const then = now + seconds * 1000;
  displayTimeLeft(seconds);
  displayEndTime(then);

  countdown = setInterval(() => {
    // ...
    displayTimeLeft(secondsLeft);
  }, 1000);
}

function displayTimeLeft(seconds) {
}

function displayEndTime(timestamp) {
}

先來處理 displayTimeLeft(seconds),這裡就以時間的總秒數做除和取餘數的運算,求出剩餘分鐘和剩餘秒數,再將值賦給 timerDisplaydocument.title

備註:在秒數小於 10 時需在個位數前補零,以三元運算子實現

function displayTimeLeft(seconds) {
  const minutes = Math.floor(seconds / 60);
  const remainderSeconds = seconds % 60;
  const display = `${minutes}:${remainderSeconds < 10 ? '0' : '' }${remainderSeconds}`;
  document.title = display;
  timerDisplay.textContent = display;
}


再來處理 displayEndTime(timestamp),這裡以計算好的 then 目前時間建立 Date 物件,再分別取出十二小時制的小時和分鐘,並賦值至 endTime

備註:在分鐘數小於 10 時需在個位數前補零,以三元運算子實現

function displayEndTime(timestamp) {
  const end = new Date(timestamp);
  const hour = end.getHours();
  const adjustedHour = hour > 12 ? hour - 12 : hour;
  const minutes = end.getMinutes();
  endTime.textContent = `Be Back At ${adjustedHour}:${minutes < 10 ? '0' : ''}${minutes}`;
}


最後再讓我們加上自定義倒數時間的文字輸入框,這裡做的事情比較簡單,讀入輸入後轉換成秒,再呼叫計時器而已

document.customForm.addEventListener('submit', function(e) {
  e.preventDefault();
  const mins = this.minutes.value;
  console.log(mins);
  timer(mins * 60);
  this.reset();
});

最後程式碼

const timerDisplay = document.querySelector('.display__time-left');
const endTime = document.querySelector('.display__end-time');
const buttons = document.querySelectorAll('[data-time]');

let countdown;

function timer(seconds) {
  clearInterval(countdown);
  const now = Date.now();
  const then = now + seconds * 1000;
  displayTimeLeft(seconds)
  displayEndTime(then)

  countdown = setInterval(() => {
    const secondsLeft = Math.round((then - Date.now()) / 1000);
    // check if we should stop it!
    if(secondsLeft < 0) {
      clearInterval(countdown);
      return;
    }
    console.log(secondsLeft);
    displayTimeLeft(secondsLeft);
  }, 1000);
}

function displayTimeLeft(seconds) {
  const minutes = Math.floor(seconds / 60);
  const remainderSeconds = seconds % 60;
  const display = `${minutes}:${remainderSeconds < 10 ? '0' : '' }${remainderSeconds}`;
  document.title = display;
  timerDisplay.textContent = display;
}

function displayEndTime(timestamp) {
  const end = new Date(timestamp);
  const hour = end.getHours();
  const adjustedHour = hour > 12 ? hour - 12 : hour;
  const minutes = end.getMinutes();
  endTime.textContent = `Be Back At ${adjustedHour}:${minutes < 10 ? '0' : ''}${minutes}`;
}

function startTimer() {
  const seconds = parseInt(this.dataset.time);
  timer(seconds);
}

buttons.forEach(button => button.addEventListener('click', startTimer));
document.customForm.addEventListener('submit', function(e) {
  e.preventDefault();
  const mins = this.minutes.value;
  console.log(mins);
  timer(mins * 60);
  this.reset();
});

完成結果

最後的成品

結語

以上是第二十九天的製作紀錄,如有錯誤或不足的地方還請多多指教 >.<

Vanilla JS Countdown Timer - #JavaScript30 29/30
[ Alex 宅幹嘛 ] ?‍? 深入淺出 Javascript30 快速導覽 | Day 29:Countdown Timer
MDN Web Docs


上一篇
JS30 -> 28-Video Speed Controller
下一篇
JS30 -> 30 - Whack A Mole
系列文
剛接觸前端一個月的小白 - JavaScript30 挑戰筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言