실시간 시계를 만들 일이 생겼었습니다.
setInterval, setTimeout, requestAnimationFrame 셋 중에
requestAnimationFrame을 통해 만들기로 결정했습니다.
그 이유는 전에 setInterval, setTimeout이 시간이 지남에 따라 미세하게 밀렸었던 경험이 있고, 링크에도 나와있다시피 불필요한 콜 스택이 많이 호출된다(성능 이슈). 마지막으로 찾아보다 알게 된 건데 모니터의 표시 가능한 주사율에 영향을 받는다는 점 이 때문에 requestAnimationFrame으로 구현했습니다.
requestAnimationFrame으로 애니메이션을 만들었을 때의 특징으로는 위에서 얘기한 콜 스택, 주사율 등등 외에
- 백그라운드 동작 혹은 비활성화 시 중지
- 최대 1ms 제한 = 1초당 60프레임
- 다수의 애니메이션이 동일한 타임을 참조
등이 있습니다. 하지만, Maximum Calltack이 발생할 수 있기에 조건을 걸어주는 등 적 잘한 조치가 필요합니다.
현재 시간 가져오기
// current date info
function dateInfo(staticDate = new Date()) {
const currentDate = staticDate;
const year = currentDate.getFullYear();
const month = currentDate.getMonth() + 1;
const date = currentDate.getDate();
const hour = currentDate.getHours();
const min = currentDate.getMinutes();
return { currentDate, year, month, date, hour, min };
}
// set real time
function setRealTime() {
let { currentDate, year, month, date, hour, min } = dateInfo();
const ampm = hour >= 12 ? 'PM' : 'AM';
hour = modifyTimeUnit(hour);
min = modifyTimeUnit(min);
return { ampm, hour, min, date, month, year };
}
// modify time unit
function modifyTimeUnit(time) {
if (time < 10) return '0' + time;
return time;
}
저는 필요에 의해 dateInfo, setRealTime 함수 두 개로 나눴지만, 굳이 나눌 필요는 없습니다.
우선 dateInfo함수에서 년, 월, 일, 시, 분 정보를 변수에 담아 객체 형태로 리턴해준 후에
setRealTime함수에서 지금이 오전/오후인지, 그리고 한 자릿수 일 때 modifyTimeUnit 함수를 이용해서 앞에 0을 붙여 2 자릿수로 통일시켜줬습니다.
(dateInfo함수 안에 month부분에 +1을 해준 이유는 getMonth()로 달 정보를 받아오면 0~11까지 리턴해주기에 1월~12월을 맞추기 위함입니다.)
const test = setRealTime();
console.log(test)
// result
// {
// ampm: "PM"
// date: 6
// hour: 18
// min: 12
// month: 9
// year: 2022
// }
결과
실행하기
requestAnimationFrame을 할당할 변수를 생성 후 시작 함수를 만들어 봅시다.
let timerAF;
function startRealTime() {
let { ampm, hour, min, date, month, year } = setRealTime();
timerAF = requestAnimationFrame(startRealTime);
console.log(`${year}.${month}.${date} ${ampm} ${hour}:${min}`);
}
startRealTime();
// 실행 결과
// 2022.9.6 PM 18:41
// ...
startRealTime 함수를 requestAnimationFrame(startRealTime)을 통해 재귀적으로 실행합니다.
그러면 setRealTime함수를 재호출 하면서 새로운 실시간 날짜 데이터를 생성하고, 가공된 해당 데이터를 받아와서 콘솔에 뿌려주게 됩니다.
const elem = document.querySelector('.currunt-time');
elem.innerText = `${year}.${month}.${date} ${ampm} ${hour}:${min}`;
콘솔 대신 이런 식으로 사용하시면 DOM에도 표시가 됩니다.
(초를 받아오고 있진 않아서 분이 변경될 때마다 text가 변할 겁니다.)
저런 방식을 통해 날짜 데이터에서 가져올 항목을 제거하거나 추가하여 본인의 필요에 맞게 가공 후 사용하시면 되겠습니다.
아 마지막으로 requestAnimationFrame(startRealTime)가 아니라 requestAnimationFrame(startRealTime())이렇게 함수를 호출해버리면 Maximum Calltack이 뜨니 주의하세요!
피드백 및 코멘트는 언제나 환영입니다!
감사합니다 :)
'개발 > js' 카테고리의 다른 글
[JS] model-viewer 사용법 4 - model AR 활성화 및 커스텀 하기 (0) | 2022.09.15 |
---|---|
[JS] model-viewer 사용법 3 - model control 하기 (zoom in/out, animation toggle, full screen) (2) | 2022.09.14 |
[JS] model-viewer 사용법 2 - model animation 추가하기 (with. modal 닫기) (0) | 2022.09.13 |
[JS] model-viewer 사용법 1 - web에 3D 모델을 띄우자! (0) | 2022.09.13 |
JS - try/catch문 404 Error 핸들링하기 (0) | 2022.09.01 |