2023. 10. 24. 16:25ㆍWEB Dev/StudyNote
리사트 파밍챌린지 프론트엔드 개발자편 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를 주었다.
회고
오랜만에 스스로 하는 작업이어서 시작부터 좀 떨렸다. (아니 부담이었다)
타이머 기능은 이전에 쇼핑몰 작업 때 할인 종료 시간으로 만들었던 적이 있어 어렴풋이 기억났는데 매번 시간 공식 계산을 까먹어서 구글링을 해야 한다 😅
'WEB Dev > StudyNote' 카테고리의 다른 글
[TypeScript] GraphQL과 타입스크립트로 개발하는 웹 서비스 스터디 15, 16 (0) | 2023.06.19 |
---|---|
[TypeScript] GraphQL과 타입스크립트로 개발하는 웹 서비스 스터디 14 (0) | 2023.05.28 |
[TypeScript] GraphQL과 타입스크립트로 개발하는 웹 서비스 스터디 13 (0) | 2023.05.21 |
[TypeScript] GraphQL과 타입스크립트로 개발하는 웹 서비스 스터디 12 (0) | 2023.05.14 |
[TypeScript] GraphQL과 타입스크립트로 개발하는 웹 서비스 스터디 11 (0) | 2023.05.07 |