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함수는 가끔 요상하게 움직이기 때문에.....알아두면 좋은 트릭이다.
다른 버튼을 눌렀을 때 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을 붙여주자.
됐다!
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)
}