Day29 Countdown Timer

Demo

對象和事件

1
2
3
4
5
6
7
8
9
let countdown; //setInterval計時器
const timer_btn = document.querySelectorAll('.timer__button')
const timerDisplay = document.querySelector('.display__time-left');
const endTime = document.querySelector('.display__end-time');

function getTime(){
//..
}
timer_btn.forEach((btn)=>{btn.addEventListener('click',getTime)})

我們會有一個setInterval計時器,所以先建立一個countdown計時器名稱
以及我們的觸發按鈕、顯示倒數、顯示到期

接下來我們會觸發一系列的涵式
取得時間–>計算時間–>顯示剩餘和到期時間

取得時間

時間資料已經寫在data-time裡面,點下按鈕時將資料取出:

1
2
3
4
function getTime(){
const getSec = parseInt(this.dataset.time)
startTimer(getSec)
}

呼叫startTimer,並將取得的秒數傳入

計算時間

我們需要操作三個時間:

  • 現在時間:Date.now()
  • 到期時間:現在時間 + 指定時間(我們傳入的指定seconds)
  • 剩下時間:到期時間 - 現在時間
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function startTimer(seconds){
clearInterval(countdown);//關閉正在執行的倒數
const now = Date.now() //取得現在的timestamp
const deadline = now + seconds*1000 //截止時間

formatTime(seconds) //馬上顯示起始時間
formatDeadline(deadline)//馬上顯示結束時間

countdown = setInterval(()=>{
const remain = Math.round((deadline - Date.now())/1000)
//小於0就停止計時
if(remain < 0) {
clearInterval(countdown);
return;
}
formatTime(remain)//傳remain值去做格式化並顯示
},1000)
}

透過setInterval每秒去取得剩餘時間

注意:「剩下時間 = 到期時間 - 現在時間」,此時的現在時間我們不是去呼叫now,而是重新再取一次時間Date.now()因為時間是一直前進的。

顯示剩餘時間

我們在setInterval計算出剩餘時間後,再將直傳入formatTime來渲染到畫面上

1
2
3
4
5
6
7
function formatTime(remain){
const min = Math.floor(remain/60)
const sec = remain%60
const show = `${min}:${sec < 10 ? '0' : '' }${sec}`
document.title = show;
timerDisplay.textContent = show;
}

當然我們要將timestamp轉換成時間格式,完成後傳到指定的元素即可。

補充:${sec < 10 ? '0' : '' }讓秒數有兩位數

顯示到期時間

因為到期時間只需呼叫一次,所以不要放到setInterval

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function startTimer(seconds){
//..
formatTime(seconds) //馬上顯示起始時間
formatDeadline(deadline)//馬上顯示結束時間
//...
}

function formatTime(remain){
const min = Math.floor(remain/60)
const sec = remain%60
const show = `${min}:${sec < 10 ? '0' : '' }${sec}`
document.title = show;
timerDisplay.textContent = show;
}

在這邊我們立即呼叫了formatTimeformatDeadline兩個涵式,為的是希望畫面在觸發後,能先顯示資訊,而非等待setInterval一秒後才顯示。

客製時間

customForm為範例html表單的name,可以直接選取,並給予submit事件
this.minutes.value意即form裡面input-name為minutes的值
取得值後帶入我們一開始的startTimer()涵式中,
要注意的是我們涵式是接收秒數來做計算`所以要轉成秒數

1
2
3
4
5
6
document.customForm.addEventListener('submit', function(e) {
e.preventDefault();//關閉預設送出功能
const customval = this.minutes.value
startTimer(customval*60)
this.reset();//重設表單
})

補充筆記:時間格式轉換

  1. 取得時間

    1
    2
    const now = new Date()
    //不給值就是取出電腦當下時間,給timestamp值就是取出指定時間。
  2. 取得timestamp

    1
    2
    3
    const now = Date.now();
    //OR
    // const now = (new Date()).getTime()
  3. 網路範例

    1
    2
    3
    4
    var d = new Date("Wed Jun 20 19:20:44 +0000 2012");
    d.getTime(); //returns 1340220044000
    //OR
    Date.parse("Wed Jun 20 19:20:44 +0000 2012"); //returns 1340220044000

完整程式碼

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
let countdown;
const timer_btn = document.querySelectorAll('.timer__button')
const timerDisplay = document.querySelector('.display__time-left');
const endTime = document.querySelector('.display__end-time');

function startTimer(seconds){
clearInterval(countdown);//關閉正在執行的倒數
const now = Date.now() //取得現在的timestamp
const deadline = now + seconds*1000 //截止時間

formatTime(seconds) //馬上顯示起始時間
formatDeadline(deadline)//馬上顯示結束時間

countdown = setInterval(()=>{
const remain = Math.round((deadline - Date.now())/1000)
//小於0就停止計時
if(remain < 0) {
clearInterval(countdown);
return;
}
formatTime(remain)//傳remain值去做格式化並顯示
},1000)
}

function formatTime(remain){
const min = Math.floor(remain/60)
const sec = remain%60
const show = `${min}:${sec < 10 ? '0' : '' }${sec}`
document.title = show;
timerDisplay.textContent = show;
}

function formatDeadline(deadline){
const end = new Date(deadline)//直接把timestamp轉乘時間格式
const hour = end.getHours()
const min = end.getMinutes()
endTime.textContent = `到期時間:${hour}:${min}`
}

function getTime(){
const getSec = parseInt(this.dataset.time)
startTimer(getSec)
}

timer_btn.forEach((btn)=>{btn.addEventListener('click',getTime)})
document.customForm.addEventListener('submit', function(e) {
e.preventDefault();//關閉預設送出功能
const customval = this.minutes.value
startTimer(customval*60)
this.reset();//重設表單
})
0%