[JS30] -29) Countdown Clock

버튼을 누르거나 시간을 입력했을 때 화면에 띄우기

const $timerDisplay = document.querySelector('.display__time-left');

const $customForm = document.querySelector('#custom');
const $customTimeInput = document.querySelector('input[name="minutes"]');
const $timerButtons = document.querySelectorAll('.timer__button');

$customForm.addEventListener('submit', handleCustomTimeInput)
$timerButtons.forEach(($timerButton) => {
    $timerButton.addEventListener('click',() => displayCountdown(
        $timerButton.dataset.time
    ))
})


function handleCustomTimeInput(e) {
    e.preventDefault();
    displayCountdown($customTimeInput.value);
}

function displayCountdown(seconds) {
    const min = Math.floor(seconds / 60);
    const secondsLeft = seconds % 60;
    $timerDisplay.textContent = `${min} : ${secondsLeft}`;
}

시간 계산하기

어떤 다른 방법으로 일정한 타이머를 구현할 수 있을까?

타이머 만들기

function timer(seconds) {
  const now = Date.now();
  const then = now + seconds * 1000;
  
  setInterval(() => {
  	const secondsLeft = Math.round((then - Date.now()) / 1000);
    console.log(secondsLeft);
    
  }, 1000);

seconds를 넣으면, 현재 시각에서 넣은 seconds를 더한다.
그 뒤 현재시각을 1초마다 받아와 빼준다.

헷갈린다면 아래 그림을 참고하자.

그냥 1초마다 지정한 시간에서 1초씩 빼면 되는 거 아니야?

굳이 이렇게 번거롭게 하는 이유가 있다.
브라우저가 버벅이거나 맥에서 스크롤하는 등의 특정 상황에서 setInterval함수가 원활히 작동하지 않을 수 있다. 그런 경우에도 계속해서 현재시간을 받아와 빼준다면 금방 정상화되기 때문에, 위와 같이 하는 것이다.

setInterval함수는 가끔 요상하게 움직이기 때문에.....알아두면 좋은 트릭이다.

clearInterval로 타이머 초기화

다른 버튼을 눌렀을 때 setInterval함수가 겹치지 않아야 하기 때문에, 함수가 실행되었더라도 초기화할 수 있도록 가장 처음에 clearInterval을 해준다. 타이머를 선언한 이전에 clearInterval을 해주어야 하기 때문에 미리 let으로 최상단에 선언해준다음 할당해주었다.

맨 처음 자바스크립트로 게임을 만들 때가 떠올랐다...그 때 setInterval을 처음 다루면서 두 개의 함수가 겹치거나 clearInterval을 제대로 못 써서 곤란했었는데, 함수 처음에 clearInterval로 초기화 해주는 건 아주 좋은 방법인 것 같다. 기억하자!

let countdown;

function timer(seconds) {
    clearInterval(countdown);

    const now = Date.now();
    const then = now + seconds * 1000;
    countdown = setInterval(() => {

        const secondsLeft = Math.round((then - Date.now()) / 1000);
        displayCountdown(secondsLeft)
        if(secondsLeft <= 0) clearInterval(countdown);
    }, 1000)
}

한 자리 수 앞에 0붙이기

너무 멋이 없다.
한 자리 수 일때는 앞에 0을 붙여주자.

됐다!

카운트 다운 종료 시점 표시하기

function displayEndTime(time) {
    const date = new Date(time);
    const hour = date.getHours();
    const minutes = date.getMinutes();
    const seconds = date.getSeconds();

    $endTime.textContent = `${hour}${minutes}${seconds}초에 종료됩니다`
}

function timer(seconds) {
    clearInterval(countdown);

    const now = Date.now();
    const then = now + seconds * 1000;

    displayEndTime(then);//
    countdown = setInterval(() => {

        const secondsLeft = Math.round((then - Date.now()) / 1000);
        displayCountdown(secondsLeft)
        console.log(secondsLeft)
        if(secondsLeft <= 0) clearInterval(countdown);
    }, 1000)
}

맨 처음 카운트 다운할 시간을 입력받으면, Date.now()값에 카운트 다운할 시간을 더한 then을 만들었었다. 이것이 우리가 이동할 시간이므로, displayEndTime(then)을 해주면 된다.

타이머 시작시 첫 화면 표시하기

아래와 같이 setInterval이 시작되어 1초가 지나야만 화면에 남은 시간이 표시되기 떄문에
첫화면에서 시간을 표시해주어야 한다.

function timer(seconds) {
    clearInterval(countdown);

    const now = Date.now();
    const then = now + seconds * 1000;
    displayCountdown(seconds)//

    displayEndTime(then);
    countdown = setInterval(() => {

        const secondsLeft = Math.round((then - Date.now()) / 1000);
        displayCountdown(secondsLeft)
        console.log(secondsLeft)
        if(secondsLeft <= 0) clearInterval(countdown);
    }, 1000)
}

좋은 웹페이지 즐겨찾기