提供使用者直接輸入想要倒數的分鐘數,另外也提供快捷鍵的倒數選項。
一邊告訴你剩下多少時間,底下也顯示幾點幾分時間到。
個人codepen
直接從程式碼紀錄操作過程
<button data-time="20" class="timer__button">20 Secs</button>
const controls = document.querySelectorAll(".timer__button");
// 將所有的快捷按鈕綁定監聽,並從自訂義的屬性dataset中取出秒數資料。此秒數為字串,所以用parseInt將其轉換為數字,再做處理。
controls.forEach(button => {
button.addEventListener('click', function() {
const seconds = parseInt(this.dataset.time);
startTimer(seconds);
});
});
// 設定定時器變數
let timer;
function startTimer(seconds) {
// 一進入函式要先清除定時器,因為使用者可能反覆去點擊不同快捷按鈕,會觸發多次計時器。
clearInterval(timer);
// 計算結束的時間,那因為Date.now()的數值會是毫秒數,一秒等於1000毫秒,先轉換成毫秒,再相加,就可以知道接下來要結束的時間。再將她處理成文字,渲染在畫面。
const endTime = Date.now() + seconds * 1000;
updateEndTime(endTime);
// 處理每秒倒數顯示的時間,要先處理一次,不然使用者設定倒數時間送出後,第一時間看不到倒數的秒數。等下次看到已經過了一秒。
displayTime(seconds);
// 設定間隔計時器,每隔一秒就計算一次,目前的時間和結束的時間之差距。
timer = setInterval(() => {
// 結束的時間是固定的,但現在的時間會每秒變動。相差的值因為是毫秒數,要先除於1000轉換為秒數,因為數字不會剛好,所要再用Math.round四捨五入。
const remainingSeconds = Math.round((endTime - Date.now()) / 1000);
// 秒數如果變成負值的時候,代表計時器倒數結束,要清除定時器,並且終止函式繼續向下運行。
if (remainingSeconds < 0) {
window.alert("time up");
clearInterval(timer);
return;
}
// 倒數秒數還是正值的情況,就要繼續更新畫面中的倒數數字。
displayTime(remainingSeconds);
}, 1000);
}
處理畫面中的倒數數字更新
function displayTime(seconds) {
// 秒數除於60可以知道幾分鐘,那因為會有小數點,小數點代表不到一分鐘,所以直接Math.floor無條件捨去。
const minutes = Math.floor(seconds / 60);
// 一分鐘為60秒,所以將秒數跟60取餘數,剩下的就會是秒數了。
const remainderSeconds = seconds % 60;
// 處理畫面中的倒數數字的更新
countDownTxt.textContent = `${String(minutes).padStart(2, '0')} : ${String(remainderSeconds).padStart(2, '0')}`;
}
處理畫面中預計結束時間的文字
function updateEndTime(timestamp) {
// 傳過來的是毫秒數,放入到new Date可以得到現在的時間。
const end = new Date(timestamp);
// 取時間的數字
const hours = end.getHours();
// 取分鐘的數字
const minutes = end.getMinutes();
// 因為小時會是24小時制,所以要額外判斷是否超過12點
const newHours = hours > 12 ? hours - 12 : hours;
const amPm = hours >= 12 ? '下午' : '上午';
// 將時間的數字,只有一位數時,就補0上去,這樣比較美觀
endTimeTxt.textContent = `Be Back at:${amPm} ${String(newHours).padStart(2, '0')} : ${String(minutes).padStart(2, '0')}`;
}
會從字串的左側開始添加指定字元,一直重複添加到指定的長度。
targetLength為填充後的字元長度,padString為想要添加的字元。padString預設是空白。
// 字串原本長度為2,需要添加字元到長度為5為止,因為padString沒設定,預設就是填充空白插入。
"IT".padStart(5); // " IT"
"IT".padStart(10, "what is "); // "'what is IT'"
// 填充123456到abc中,但因為只需要填充到6的長度,所以後面456就沒用到了。
"abc".padStart(6, "123456"); // "123abc"
倒數的秒數只有一個位數時,會變成10:9的方式出現,為了美觀要把它變成10:09,因此需要額外處理秒數。
parseInt會忽略前後空白,並根據radix進位系統去解析,當遇到無法解析的字元,會忽略該字元及其後的所有字元,並停止繼續解析剩餘的文字,然後回傳目前為止的結果。
parseInt(" 123",10) // 123 忽略前面空白
parseInt("") // 無法解析返回NaN
parseInt("16px",10) // 16 後面的英文字母無法解析成數字,所以只返回前面的16
parseInt(" 777 ",10) //777,前面空白忽略,直接解析777,後面遇到空白也會停止解析
主要是時間相關方法的熟練度,要轉來轉去的,轉到後面我都暈了。
表單的form預設submit行為記得要preventDefault。另外輸入欄位可能會出現非數字的行為,要先做判斷處理,用parseInt()將字串轉成數字,遇到不能轉成數字的話,會出現NaN的狀況。或是數字會有負數。就可以擋掉,並給使用者提示,請他好好輸入!不要害我畫面出現NaN...