[리사트파밍챌린지] day02 타이머 만들기

2023. 10. 24. 16:25WEB Dev/StudyNote

728x90

 

리사트 파밍챌린지 프론트엔드 개발자편 4기

 


문제

위와 같은 형태로 된 타이머 만들기

 

 


 

레이아웃

 

우선 HTML과 CSS로 기본 틀을 잡는다.

form-fieldset-input을 추가하여 입력 창을 만들고, placeholder로 00을 입력했다.

placeholder는 실제 입력 시 사라진다.

3개의 버튼은 동일한 디자인으로 만들었고, flex를 이용하여 space-between으로 간격을 맞췄다.

box-shadow로 멋을 좀 부려 보았다.

 

기능

 

만들어야 하는 기능은 다음과 같다

 

- START 버튼을 누르면 시간, 분, 초 단위로 카운트 다운 작동 (시간, 분, 초를 입력하는 영역이 사라진다)
- STOP 버튼을 누르면 카운트 다운을 정지한다.
- RESET 버튼을 누르면 모든 항목 0으로 초기화 되면서 다시 시간,분,초를 입력하는 영역이 나타난다.

 

 

구현

- START 버튼을 누르면 시간, 분, 초 단위로 카운트 다운 작동

(시간, 분, 초를 입력하는 영역이 사라진다)

 

버튼과 input의 클래스명을 사용해 각각 변수에 할당해준다.

input이라는 변수로 input 요소들을 배열로 만들어 준다.

 

/*버튼 정의 */

const start_btn = document.querySelector(".start_btn");
const stop_btn = document.querySelector(".stop_btn");
const reset_btn = document.querySelector(".reset_btn");

/* input 정의 */

const input = document.querySelectorAll(".time_input");
const hour = document.querySelector(".hour");
const minute = document.querySelector(".minute");
const seconds = document.querySelector(".seconds");

 

start 버튼을 눌렀을 때 input들이 disabled 되어야 한다. (시, 분 초 input 사라짐)

start_btn 에 이벤트리스너를 만들고 input 배열을 반복할 수 있는 객체로 만들기 위해 [...input]으로 변경한다.

각 input들에게 disabled라는 속성을 주고 true 값을 할당한다.

 

/* START 버튼 누르면 시간 분 단위로 카운트다운 / 시분초 input 사라짐 */

start_btn.addEventListener("click", (e)=>{

	/* 시분초 input 사라짐*/
	[...input].forEach((input)=>{
		input.setAttribute("disabled", "true")
	})

})

 

input 값들은 모두 입력하지 않을 수도 있기 때문에 에러 처리를 위해 미리 input들의 값을 확인하고 값이 없으면 00을 넣는 코드를 작성했다.

 

/* START 버튼 누르면 시간 분 단위로 카운트다운 / 시분초 input 사라짐 */

start_btn.addEventListener("click", (e)=>{

	/* 시분초 입력 안할 경우 00으로 변경 */
	[...input].forEach(input=>{
		input.value === "" ? input.value="00" : null;
	})


	/* 시분초 input 사라짐*/
	[...input].forEach((input)=>{
		input.setAttribute("disabled", "true")
	})

})

 

그리고 유저가 입력한 시간을 계산하기 위해 각각의 input의 값을 받아와 '초'로 만든다.

보통 시간계산을 할 때는 전부 초로 변경해놓고 각각을 다시 변환하는 과정을 거친다.

 

여기서 숫자 계산을 거쳐야 하기 때문에 각 값을 parseInt로 정수 처리 하는 것을 잊지 말자.

(정수 처리 안하면 시 분이 이상하게 꼬임..)

 

/* START 버튼 누르면 시간 분 단위로 카운트다운 / 시분초 input 사라짐 */

start_btn.addEventListener("click", (e)=>{
	
	/* 시분초 입력 안할 경우 00으로 변경 */
	[...input].forEach(input=>{
		input.value === "" ? input.value="00" : null;
	})

	const hrs = parseInt(hour.value);
	const min = parseInt(minute.value);
	const sec = parseInt( seconds.value);

	const totalSec = (hrs * 60 * 60) + (min * 60) + sec;

	/* 시분초 input 사라짐*/
	[...input].forEach((input)=>{
		input.setAttribute("disabled", "true")
	})

})

 

만들어진 totalSec을 이용해 타이머를 돌릴 수 있다.

이를 위해 별도의 타이머 함수를 만든다.

timerStart라는 이름으로 함수를 하나 만들고, 인자로 totalTime을 받는다.

 

보통 타이머나 시계는 setInterval이라는 함수를 사용하는데 setInterval(()=>{}, 시간) 을 기본형으로 한다.

콜백 함수에 실행할 기능을 넣고 시간에 1000을 입력하면 시간은 ms(밀리세컨즈)로 인식하여 1초에 한 번씩 콜백함수를 실행하게 된다.

나중에 이 setInterval을 정지도 해야 하기 때문에 i라는 변수에 setInterval을 할당해준다. 

 

/* 타이머 함수  */

const timerStart = (totalTime) => {
	i = setInterval(()=>{

	},1000)
}

 

여기서 받은 인자인 totalTime은 초로 되어 있기 때문에 타이머처럼 움직이게 하기 위해서는 1씩 감소하면 된다.

tatalTime 인자를 -- 로 빼준다.

 

/* 타이머 함수  */

const timerStart = (totalTime) => {
	i = setInterval(()=>{
		totalTime--;

	},1000)
}

 

 

이렇게 1초에 1초씩 빠지는 코드가 만들어지면 변경되고 있는 totalTime을 이용해서 각 input 자리에 value로 할당해준다.

이를 위해 실제 시간들을 구해야 한다.

아래와 같이 totalTime을 다시 60으로 나누어 주면 되는데 

여기서 real_minutes와 real_second를 구하는 방법에 % 나머지 연산자가 있으니 유의하자.

나눠주게 되면 소숫점 자리까지 구해지는데 이를 제거하기 위해 Math.floor 메소드를 사용한다.

그리고 각각 구해준 시간, 분, 초를 input에 값에 할당해준다.

 

/* 타이머 함수  */

const timerStart = (totalTime) => {
	i = setInterval(()=>{
		totalTime--;

		const real_hours =  Math.floor(totalTime / 60 / 60);
		const real_minutes = Math.floor((totalTime / 60) % 60)
		const real_seconds = totalTime % 60;

		hour.value = real_hours;
		minute.value = real_minutes;
		seconds.value = real_seconds;

	},1000)
}

 

여기서 구해지는 시, 분, 초는 앞자리에 0이 없어지고 정수로만 출력된다.

이를 더 예쁘게 구현하기 위해 1,2,3 같이 10보다 작아 두 자리가 안 되는 경우에 앞에 0을 더하는 조건문을 생성한다.

 

/* 타이머 함수  */

const timerStart = (totalTime) => {
	i = setInterval(()=>{
		totalTime--;

		const real_hours =  Math.floor(totalTime / 60 / 60);
		const real_minutes = Math.floor((totalTime / 60) % 60)
		const real_seconds = totalTime % 60;

		hour.value = real_hours;
		minute.value = real_minutes;
		seconds.value = real_seconds;
        
        /* 한 자리 숫자에 앞 0 붙이기 */

		if(real_hours < 10){
			hour.value = '0'+real_hours;
		}
		if(real_minutes < 10){
			minute.value = '0'+real_minutes;
		}
		if(real_seconds < 10){
			seconds.value = '0'+real_seconds;
		}

	},1000)
}

 

이렇게 1초 마다 움직이면서 숫자가 잘 변화되고 있으면 나머지 기능은 간단하다.

 

 

- STOP 버튼을 누르면 카운트 다운을 정지한다.

 

clearInterval 함수로 setInterval 함수를 멈춰주면 되는데 사용법은 간단하다.

아래와 같이 할당된 setInterval의 이름인 i를 clearInterval로 멈춰주면 타이머 동작이 멈춘다.

 

/* 타이머 스톱  */

stop_btn.addEventListener("click", (e)=>{
	clearInterval(i);
})

 

 

- RESET 버튼을 누르면 모든 항목 0으로 초기화 되면서 다시 시간,분,초를 입력하는 영역이 나타난다.

 

이제 RESET 버튼의 기능을 만드는데 이 또한 동일하게 clearInterval을 통해서 작동을 멈추고,

각 input의 값을 공란으로 만들어주면 자동으로 placeholder에 있는 00이 표시되게 된다.

또한 다시 시, 분, 초를 입력하는 영역이 동작해야 하기 때문에 input을 forEach로 돌려 disabled 속성을 삭제해준다.

 

/* 타이머 리셋  */
reset_btn.addEventListener("click", (e)=>{
	clearInterval(i);
	hour.value = "";
	minute.value = "";
	seconds.value = "";

    /* 시분초 input 사라짐*/
    [...input].forEach((input)=>{
        input.removeAttribute("disabled")
    })
})

 

그리고 자잘한 CSS적 문제나 디자인, 애니메이션을 정리하여 수정한다.

각 input에는 음수가 들어가지 않도록 min="0" 값 속성을 주었고 분, 초에는 max 값으로 59를 주었다.

 

 

회고

오랜만에 스스로 하는 작업이어서 시작부터 좀 떨렸다. (아니 부담이었다)

타이머 기능은 이전에 쇼핑몰 작업 때 할인 종료 시간으로 만들었던 적이 있어 어렴풋이 기억났는데 매번 시간 공식 계산을 까먹어서 구글링을 해야 한다 😅

 

 

728x90