Theme NexT works best with JavaScript enabled

ShunNien's Blog

不積跬步,無以致千里;不積小流,無以成江海。

0%

JS30紀錄 29-Countdown Timer

目標

製作一個倒數計時器,頁面上已經有固定秒數的選項,也有 form 的自訂時間的倒數
target

Demo | Github

處理步驟

要製作一個倒數計時器,就要使用到 setInterval ,練習的範本上已經有幾個固定秒數按鈕,所以先把顯示文字呈現出來,最後在處理計時器

步驟 1.

顯示文字的部分有兩個,一個是倒數計時,一個是時間截止的時間,另外還要變更網頁標題(頁籤上的標題文字)

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
28
29
30
31
32
33
34
35
// 取得所有 buttons
const buttons = document.querySelectorAll("[data-time]");

// 倒數計時的顯示元素
const timerDisplay = document.querySelector(".display__time-left");
// 結束時間的顯示元素
const endTime = document.querySelector(".display__end-time");

/**
* 顯示倒數計時
* @param {*} seconds 秒數
*/
function displayTimeLeft(seconds) {
// 計算幾分鐘
const minutes = Math.floor(seconds / 60);
// 計算剩餘秒數
const remainderSeconds = seconds % 60;
// 組合顯示文字(剩餘時間)
const display = `${minutes}:${remainderSeconds}`;
// 變更網頁標題
document.title = display;
// 顯示倒數計時
timerDisplay.textContent = display;
}

/**
* 顯示結束時刻
* @param {*} timestamp
*/
function displayEndTime(timestamp) {
// 轉換為時間
const end = new Date(timestamp);
// 顯示結束時間
endTime.textContent = `Be Back At ${end.getHours()}:${end.getMinutes()}:${end.getSeconds()}`;
}

步驟 2.

各按鈕事件與計時器撰寫,利用 setInterval 來顯示上一步驟的時間。由於 setInterval 設定為每秒鐘進行,所以顯示時間直接根據秒數去扣除顯示。

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
28
29
30
31
32
33
34
35
36
37
38
39
// 建立計時器
let countdown;

/**
* 按鈕事件,啟動計時器
*/
function startTimer() {
// dataset 轉換數值
const seconds = parseInt(this.dataset.time);
timer(seconds);
}

/**
* 倒數計時器
* @param {*} seconds
*/
function timer(seconds) {
// 先清除其他計時器,避免相互影響
clearInterval(countdown);
// 計算倒數計時完成的時刻(使用毫秒)
const then = Date.now() + seconds * 1000;
// 顯示倒數計時
displayTimeLeft(seconds);
// 顯示完成時刻
displayEndTime(then);

countdown = setInterval(() => {
// 每秒鐘執行,所以直接每次減 1 就好
seconds--;
// 小於 0 時,清除計時器
if (seconds < 0) {
clearInterval(countdown);
return;
}
displayTimeLeft(seconds);
}, 1000);
}

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

步驟 3.

表單的自訂時間功能,同樣呼叫上一步驟的計時器;並將顯示時間的文字調整;注意表單送出的時候需要取消預設功能,避免頁面重整。

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* 顯示倒數計時
* @param {*} seconds 秒數
*/
function displayTimeLeft(seconds) {
// 計算幾分鐘
const minutes = Math.floor(seconds / 60);
// 計算剩餘秒數
const remainderSeconds = seconds % 60;
// 組合顯示文字(剩餘時間)
const display = `${paddingLeft(minutes.toString(), 2)}:${paddingLeft(
remainderSeconds.toString(),
2
)}`;
// 變更網頁標題
document.title = display;
// 顯示倒數計時
timerDisplay.textContent = display;
}

/**
* 顯示結束時刻
* @param {*} timestamp
*/
function displayEndTime(timestamp) {
// 轉換為時間
const end = new Date(timestamp);
const hour = end.getHours().toString();
const minute = end.getMinutes().toString();
const second = end.getSeconds().toString();
// 顯示結束時間
endTime.textContent = `Be Back At ${paddingLeft(hour, 2)}:${paddingLeft(
minute,
2
)}:${paddingLeft(second, 2)}`;
}

/**
* 文字在指定長度中左邊補 0
* @param {*} str 輸入文字
* @param {*} lenght 補 0 的長度
*/
function paddingLeft(str, lenght) {
if (str.length >= lenght) return str;
else return paddingLeft("0" + str, lenght);
}

document.customForm.addEventListener("submit", function(e) {
// 取消事件
e.preventDefault();
const mins = this.minutes.value;
timer(mins * 60);
// 表單清單
this.reset();
});

筆記與備註事項

JavaScript 部分

Date.now()

Date.now() 方法回傳自 1970/01/01 00:00:00 UTC 起經過的毫秒數。
資料來源 - MDN

參考資料

歡迎關注我的其它發布渠道