今天要來做一個倒數計時器,首先我們先將所有的 buttons
都監聽起來,在點擊後,抓到設定的時間並當成參數傳入 timer()
,再抓到要顯示的區域。
const timerButtons = document.querySelectorAll('.timer__button');
const displayTimeLeft = document.querySelector('.display__time-left');
const displayEndTime = document.querySelector('.display__end-time');
function timerStart() {
const timeDiff = Number(this.dataset.time);
timer(timeDiff);
}
timerButtons.forEach(btn => btn.addEventListener('click', timerStart));
接著我們要設定一秒一次的計時器 timer
, 我們目前掌握兩件事「顯示剩餘時間」(一秒一次)和「顯示結束時間」(一次),全部都用毫秒來算才不用判別進位問題。如果剩餘秒數小於0,就清掉計時器並 return
。
function timer(timeDiff) {
const now = new Date().getTime(); //取得1970到現在的毫秒
const nowSec = Math.round(now / 1000); //換成秒
const endMillionSec = (nowSec + timeDiff) * 1000; //結束毫秒數
showTimeLeft(timeDiff); //顯示剩餘時間
showEndTime(endMillionSec); //顯示結束時間
let countDown = setInterval(function () {
secondLeft = Math.round((endMillionSec - Date.now()) / 1000);
if (secondLeft < 0) {
clearInterval(countDown);
return;
}
showTimeLeft(secondLeft); //刷新剩餘時間
}, 1000);
}
寫完上列程式碼,還不會跑起來,先把 showEndTime()
註解掉,我們先來處理 showLeftTime()
,首先我們將傳進去的秒數整理成分跟秒,最後再渲染上 html
function showTimeLeft(secondLeft) {
const minLeft = Math.floor(secondLeft / 60);
secondLeft %= 60;
const timeLeft = `${minLeft}:${secondLeft}`;
displayTimeLeft.textContent = timeLeft;
}
處理完後會發現如果連續點擊時間按鈕會有多個計時器在計時,顯示剩餘時間會跳來跳去。
這時候要修改一下,每次在設置 timer 時,先把計時器清掉。因此必須在 function
外宣告,不然會找不到 countDown
這個變數。
let countDown; //在外面宣告
function timer(timeDiff) {
clearInterval(countDown);//清掉計時器
const now = new Date().getTime();
const nowSec = Math.round(now / 1000);
const endMillionSec = (nowSec + timeDiff) * 1000;
showTimeLeft(timeDiff);
showEndTime(endMillionSec);
countDown = setInterval(function () { //不需要宣告
secondLeft = Math.round((endMillionSec - Date.now()) / 1000);
if (secondLeft < 0) {
clearInterval(countDown);
return;
}
showTimeLeft(secondLeft);
}, 1000);
}
接著我們要顯示截止時間new Date(value)
,放入結束毫秒的 value ,即可拿到結束的時間。
再將時間渲染上去。
function showEndTime(endMillionSec) {
const end = new Date(endMillionSec)
let endHr = end.getHours();
let endMin = end.getMinutes();
const endTime = `計時器將在${endHr}:${endMin}到期`;
displayEndTime.textContent = endTime;
}
現在可以來跑看看成果了!會發現還是有問題,當秒針是個位數的時候顯示的不是兩位數。
因此我們要判斷當秒數小於10的時候,會在前面補0。
function showTimeLeft(secondLeft) {
...
const timeLeft = `${minLeft}:${secondLeft < 10 ? '0': ''}${secondLeft}`;
displayTimeLeft.textContent = timeLeft;
}
function showEndTime(endMillionSec) {
...
const endTime = `計時器將在${endHr}:${endMin < 10 ? '0':''}${endMin}到期`;
displayEndTime.textContent = endTime;
}
最後我們要監聽submit
事件,要注意的是 submit 事件只有在 form 元素有效, input[type=text]
元素不能被監聽 submit 事件,當 submit 事件發生,擷取輸入值並執行計時器
const minInput = document.querySelector('#custom');
function showEndTime(endMillionSec) {
minInput.addEventListener('submit', function (e) {
e.preventDefault();
const timeDiff = this.minutes.value;
timer(timeDiff * 60);
this.reset();
});
}