29 - Countdown Timer
俗話說的好,一天一蘋果,醫生遠離我
一天一 JS,What the f*ck JavaScript?
small steps every day - 記錄著新手村日記
完成目標
做一個倒數計時器
index_START.html
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Countdown Timer</title> <link href='https://fonts.googleapis.com/css?family=Inconsolata' rel='stylesheet' type='text/css'> <link rel="stylesheet" href="style.css"> </head> <body> <div class="timer"> <div class="timer__controls"> <button data-time="20" class="timer__button">20 Secs</button> <button data-time="300" class="timer__button">Work 5</button> <button data-time="900" class="timer__button">Quick 15</button> <button data-time="1200" class="timer__button">Snack 20</button> <button data-time="3600" class="timer__button">Lunch Break</button> <form name="customForm" id="custom"> <input type="text" name="minutes" placeholder="Enter Minutes"> </form> </div> <div class="display"> <h1 class="display__time-left"></h1> <p class="display__end-time"></p> </div> </div>
<script src="scripts-START.js"></script> </body> </html>
|
Style.css
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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| html { box-sizing: border-box; font-size: 10px; background: #8E24AA; background: linear-gradient(45deg, #42a5f5 0%,#478ed1 50%,#0d47a1 100%); }
*, *:before, *:after { box-sizing: inherit; }
body { margin: 0; text-align: center; font-family: 'Inconsolata', monospace; }
.display__time-left { font-weight: 100; font-size: 20rem; margin: 0; color: white; text-shadow: 4px 4px 0 rgba(0,0,0,0.05); }
.timer { display: flex; min-height: 100vh; flex-direction: column; }
.timer__controls { display: flex; }
.timer__controls > * { flex: 1; }
.timer__controls form { flex: 1; display: flex; }
.timer__controls input { flex: 1; border: 0; padding: 2rem; }
.timer__button { background: none; border: 0; cursor: pointer; color: white; font-size: 2rem; text-transform: uppercase; background: rgba(0,0,0,0.1); border-bottom: 3px solid rgba(0,0,0,0.2); border-right: 1px solid rgba(0,0,0,0.2); padding: 1rem; font-family: 'Inconsolata', monospace; }
.timer__button:hover, .timer__button:focus { background: rgba(0,0,0,0.2); outline: 0; }
.display { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.display__end-time { font-size: 4rem; color: white; }
|
scripts-START.js
空
JS - step by step
首先,我們先將需要的元素選取起來,必須先找到點擊的按鈕、點擊按鈕後會觸發的 h1
、 p
1 2 3 4 5 6 7 8 9 10 11
| let countdown; const timerDisplay = document.querySelector('.display__time-left'); const endTime = document.querySelector('.display__end-time'); const buttons = document.querySelectorAll('[data-time]');
console.log(timerDisplay); console.log(endTime); console.log(buttons);
|
接下來,當我們觸發點擊按鈕時,我們應該先要取得現在的時間、取得倒數的時間長度、執行倒數計時、顯示剩餘的時間於 h1,顯示結束時間於 p,變數 seconds
為取得 data-attibute 中所代表的倒數計時時間並轉為數字;其中在呼叫方法 timer
之前,我們必須先執行一次 clearInterval()
將先前的 setInterval()
方法先清除掉(後續避免會有BUG),變數 now
為取得目前的時間,變數 then
為將取得的時間轉換為秒數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function startTimer() { const seconds = parseInt(this.dataset.time); timer(seconds); }
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); if(secondsLeft < 0) { clearInterval(countdown); return; } displayTimeLeft(secondsLeft); }, 1000); }
|
接下來來完成 Function 中的 displayTimeLeft
與 displayEndTime
,一個為計算倒數計時的大標題 h1
,另一個為計算結束時間為何,讓使用者可以知道倒數終止的時間為幾點幾分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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}`; }
|
最後,再加上讓使用者可以自己輸入時間的 submit
按鈕,可以客製化自己想要多少的時間
1 2 3 4 5 6 7
| document.customForm.addEventListener('submit', function(e) { e.preventDefault(); const mins = this.minutes.value; console.log(mins); timer(mins * 60); this.reset(); });
|
就大功告成啦!
JS - final
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
| let countdown; const timerDisplay = document.querySelector('.display__time-left'); const endTime = document.querySelector('.display__end-time'); const buttons = document.querySelectorAll('[data-time]');
console.log(timerDisplay);
console.log(endTime);
console.log(buttons);
buttons.forEach(button => button.addEventListener('click', startTimer));
function startTimer() { const seconds = parseInt(this.dataset.time); timer(seconds); }
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); if(secondsLeft < 0) { clearInterval(countdown); return; } 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}`; }
|
本刊同步於個人網站:http://chestertang.site/
本次範例程式碼原作者來源:https://tinyurl.com/yavm5f5n