Javascript

Javascript30 - day29 Countdown Clock

joy_lee 2021. 5. 8. 12:55

목표

카운트다운 기능 구현하기

버튼 사용해 정해진 시간을 설정하거나, 맨 오른쪽의 input을 통해 내가 원하는 시간을 입력할 수도 있다.

 

내가 작성한 코드

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
const timeLeft = document.querySelector('.display__time-left');
const endTime = document.querySelector('.display__end-time');
const buttons = document.querySelectorAll('.timer__button');
const input = document.querySelector('input');
let timerID;
let seconds;
 
function addZero(num) {
    return String(num).padStart(2'0');
}
 
function countDown(seconds) {
    const hour = parseInt(seconds / 3600);
    const min = parseInt((seconds % 3600/ 60);
    let sec = seconds % 60;
    sec = addZero(sec)
    if (hour == 0) {
        timeLeft.innerHTML = `${min}:${sec}`;
    } else {
        timeLeft.innerHTML = `${hour}:${min}:${sec}`;
    }
    seconds--;
 
    if (seconds < 0) {
        clearInterval(timerID);
    }
}
 
function beBackAt(timer = '') {
    const today = new Date();
    today.setSeconds(today.getSeconds() + timer);
 
    const hours = today.getHours();
    let minutes = today.getMinutes();
    minutes = addZero(minutes);
    console.log(`${hours}:${minutes}`);
    endTime.innerHTML = `Be Back At ${hours}:${minutes}`
}
 
function timerButton() {
    seconds = parseInt(this.dataset.time);
    countDown(seconds);
    beBackAt(seconds);
    timerID = setInterval(countDown, 1000);
}
 
function timerInput(event) {
    event.preventDefault();
    const minutes = parseInt(this.value);
    seconds = minutes * 60;
    countDown(seconds);
    beBackAt(seconds);
    timerID = setInterval(countDown, 1000);
}
 
buttons.forEach(button => button.addEventListener('click', timerButton));
input.addEventListener('submit', e => timerInput(e));
cs

button과 input에서 시간을 입력받음

전달받은 시간을 전역변수인 seconds에 입력, countDown()과 timerInput()에 입력,

countDown은 setInterval으로 1초에 한번씩 실행한다.

countDown에서는 남은 시간인 seconds를 00:00 형태로 화면에 표시한다

beBackAt에서는 남은 시간+현재시간을 계산해 언제 타이머가 끝나는지 표시한다.

 

그런데 타이머가 제대로 작동하지 않았다ㅠ

 

영상에 나온 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let countdown;

function timer(seconds) {
    // clear any existing timers
    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);
        // check if we should stop it!
        if(secondsLeft < 0) {
            clearInterval(countdown);
            return;
        }
        // display it
        displayTimeLeft(secondsLeft);
    }, 1000);
}
cs

setInterval을 위한 변수 countdown을 만든다.

clearInterval(countdown);을 해야 클릭할 때 마다 새로운 타이머가 실행된다.(없으면 입력된 모든 타이머들이 동시에 작동한다.)

Date.now()로 현재 시간을 구해주고, now + seconds로 종료시간을 구한다.

Date.now()는 1970년 1월 1일 0시 0분 0초부터 현재까지 경과된 밀리 초를 반환하므로 seconds에 1000을 곱해서 계산해줘야 한다.

countdown변수에 setInterval을 입력한다. 그래야 setInterval내부에서 clearInterval(countdown)으로 interval을 마칠 수 있다.

 

 

1
2
3
4
5
6
7
8
9
10
const timerDisplay = document.querySelector('.display__time-left');
 
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;
}
 
cs

전달받은 시간을 화면에 표시한다.

${remainderSeconds < 10 ? '0' : ''}으로 초 단위 숫자가 10보다 작으면 앞에 0을 붙여준다.

문서의 title도 시간으로 표시해준다.

 

1
2
3
4
5
6
7
8
9
10
const endTime = document.querySelector('.display__end-time');
 
function displayEndTime(timestamp) {
    const end = new Date(timestamp);
    const hours = end.getHours();
    const adjustedHours = hours > 12 ? hours - 12 : hours;
    const minutes = end.getMinutes();
    endTime.textContent = `Be Back At ${adjustedHours}:${minutes < 10'0' : ''}${minutes}`;
}
 
cs

끝나는 시간은 timer()에서 then을 입력받는다.

시간과 분을 구해서 표시한다.

24시간 표시에서 12시간 표시로 바꿔준다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const buttons = document.querySelectorAll('[data-time]');
 
function startTimer() {
    const seconds = parseInt(this.dataset.time);
    timer(seconds);
}
 
buttons.forEach(button => button.addEventListener('click', startTimer));
document.customForm.addEventListener('submit'function(e) {
    e.preventDefault();
    const mins = this.minutes.value;
    timer(mins * 60);
    this.reset();
})
cs

button의 'click'이벤트에 startTimer를 연결해준다.

button의 data-time 데이터속성을 가져와서 int형식으로 바꾸고, timer에 입력한다.

직접 시간을 입력하는 input은 document.customForm으로 선택해준다.

(<form name="customForm">인 경우에 document.customForm으로 바로 선택할 수 있다.)

기본적인 submit 이벤트를 막고 입력받은 분단위 시간을 초단위로 바꿔주고 timer에 입력, input을 비워준다.

 

새롭게 알게 된 사실

tag에 name을 설정한 경우는 document.(name)으로 바로 선택할 수 있다.

timer를 멈추는 방법 : 한 변수에 타이머를 입력하고, 내부에서 clearInterval(변수)로 멈출 수 있다.

삼항연산자를 잘 사용하자(굳이 addZero 함수를 만들 필요가 없다.)

input이 아닌 form에 event를 연결해서 e.preventDefault();를 해야 새로고침이 일어나지 않는다.