觀察 index-Start.html,會發現有四個button
每都有data-time=""
屬性/單位為秒,而另外有一個form
裡面可以供使用者輸入時間/單位為分鐘,並算出倒數時間及結束時間方別渲染於對應名稱的 html 欄位中
// 所有秒數按鈕的NodeList
const buttons = document.querySelectorAll(".timer__button");
// 使用者自行輸入表單的節點
const customForm = document.querySelector("#custom");
// 渲染結束時間的節點
const endTime = document.querySelector(".display__end-time");
// 渲染剩餘時間的節點
const timeLeft = document.querySelector(".display__time-left");
document.title
及h1
中,且是每秒更新,因此需要用到setInterval() function週期執行,且時間到後要清除週期執行,因此我們於全域宣告一個變數來存放設定的週期執行。let interval;
// 按鈕對應點擊事件
buttons.forEach((button) => {
button.addEventListener("click", handleClick);
});
// 表單對應送出事件
customForm.addEventListener("submit", handleSubmit);
function handleClick(e) {
// 取得秒數轉數字、帶入倒數計時器函式
const seconds = Number(this.dataset.time);
timer(seconds);
}
function handleSubmit(e) {
// 因為提交有我們不需要的預設行為,所以我們把預設行為關掉
e.preventDefault();
// 取得分鐘數先換算秒數再轉數字、帶入倒數計時器函式
const seconds = Number(this.minutes.value) * 60;
// 當輸入的值轉成數字不是NaN才帶入執行
if (!isNaN(seconds)) timer(seconds);
// 因為預設行為關了,所以送出後表單不會清掉,因此需要手動清掉
this.reset();
}
function timer(seconds) {
// 考量到需要重設計時器,因此觸發後我們統一清除上一次的週期執行
clearInterval(interval);
// 依照輸入的秒數換算結束時間的時間戳記
const endTimStamp = Date.now() + seconds * 1000;
// 一觸發就要先渲染一次剩餘時間於畫面上
displayTimeLeft(endTimStamp);
// 渲染結束時間畫面上的函式
displayEndTime(endTimStamp);
// 設定每秒週期執行更新剩餘時間於畫面上
interval = setInterval(() => {
displayTimeLeft(endTimStamp);
}, 1000);
}
// 將'結束時間的時間戳記'與'最新的時間戳記'記算剩餘時間並轉換我們指定格式字串
// 顯示於<h1 class="display__time-left">中
function displayTimeLeft(endTimeStamp) {
const nowTimeStamp = Date.now();
// 換算剩餘時間因為每秒執行因此有可能現在時間大於結束時間變成-1所以比0小都會是0
const leftSeconds = Math.max(
Math.round((endTimeStamp - nowTimeStamp) / 1000),
0
);
const minutes = Math.floor(leftSeconds / 60);
const seconds = leftSeconds % 60;
// 剩餘時間需要在分頁標籤及畫面上都顯示
const timeString = `${minutes}:${seconds < 10 ? "0" + seconds : seconds}`;
document.title = timeString;
timeLeft.textContent = timeString;
// 如果現在時間已超過結束間則清除週期執行
if (nowTimeStamp > endTimeStamp) {
clearInterval(interval);
}
}
// 將結束時間的時間戳記轉換我們指定格式字串
// 顯示於<p class="display__end-time">中
function displayEndTime(endTimeStamp) {
const endHours = new Date(endTimeStamp).getHours();
const endMinutes = new Date(endTimeStamp).getMinutes();
endTime.textContent = `Be back At ${endHours}:${
endMinutes < 10 ? 0 : ""
}${endMinutes}`;
}
延伸功能:如果各位有興趣可以自行添加一個暫停、繼續的按鈕,以及清除的按鈕(而不是需要在表單內填 0 或等時間到才能停止),也可以設定當時間到之後播放一段 mp3 提示聲,這樣就更像外面看到的番茄盅軟體