ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [리사트파밍챌린지] day02 타이머 만들기
    WEB Dev/StudyNote 2023. 10. 24. 16:25
    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

    댓글

Designed by Tistory.