문제상황
오늘은 캐러셀을 만들다가 유저가 반복적으로 이전, 이후를 클릭할 경우에
캐러셀 자동 넘어가기 기능을 재개하는 시점을 어떻게 잡아야 할 것인지에 대한 문제에 봉착했습니다.
캐러셀은 좌 우 로 직접 넘겨볼 수 도 있고, 가만히 놔두면 자동으로 넘어가기도 하게끔 만들고 싶었는데,
자동으로 넘어가다가 유저가 좌 우를 클릭하여 개입할 경우에 문제가 발생했습니다.
단순히 좌 우를 유저가 클릭하면 requestAnimationFrame(이하 rAF) 을 cancel 하고,
setTimeout 을 이용해 5초 뒤에 다시 rAF 를 실행하게 하였는데, 그러자 클릭할 때마다
계속해서 rAF 가 실행되어 결국 stack overflow 엔딩이 될 것이 명백했습니다.
생각한 해결책
생각한 해결책으로는, 유저가 좌, 우를 클릭할 경우 클릭한 시점의 시간을 기록해 두었다가
이를 활용해다음 클릭과의 간격을 재어서, 반복적으로 클릭하는지 여부를 체크한 뒤
반복 클릭이 아니면(마지막 클릭이 끝난지 3초정도 뒤면) 다시 rAF 를 호출하기로 하였습니다.
그리고 이 방법을 사용하니 어느정도 해결이 된 것 같습니다.
코드
먼저 rAF 코드입니다.
// 캐러셀 자동 넘어가기 request animation frame 사용하여 개선
const carouselAnimate = (timestamp) => {
// timestamp 는 rAF가 넘겨주는 경과된 시간(밀리초)
// 만약 lastTime 이 null 또는 undefined 면 lastTime 을 rAF 가 시작된 시점의 timestamp와 일치시킴
if (!lastTime) lastTime = timestamp;
// 경과 시간을 측정
const elapsed = timestamp - lastTime;
// 경과 시간이 인터벌 변수 값(3.5초) 보다 크면(지났으면)
if (elapsed > interval) {
// 현재 누적된 모든 영화의 수 구하기
// 모듈로 연산 : 먼저 다음으로 넘어가기 위해 1을 더하고, sum으로 나머지 연산 하여 0이 되면 다시 돌아감
currCarouselIndex = (currCarouselIndex + 1) % 20;
// 유튜브버튼 인덱스 5이상이면 숨기기
hideOrRevealYoutubeButton(currCarouselIndex);
// 상단 섹션 다시 그리기
changeTopVisual(accMovies[0][currCarouselIndex]);
// 유튜브 버튼에 아이디를 현재 카루셀 인덱스로 부여
btnContent.id = currCarouselIndex;
// cancel 될 때를 대비하여 다음 간격의 기준점을 설정
lastTime = timestamp;
}
animationFrameId = requestAnimationFrame(carouselAnimate);
}
다음으로 캐러셀 좌 우 클릭을 핸들링하는 함수입니다.
// 상단 캐러셀 좌우 버튼 클릭시
const handleCarousel = (e) => {
const to = e.target.innerText;
const now = Date.now();
// 이전 클릭으로부터의 시간 차이 계산
const timeSinceLastClick = now - lastClickTime;
// 인터벌 제거(자동 넘기기 제거)
cancelAnimationFrame(animationFrameId);
// 이전이면
if(to === 'navigate_before'){
// ... 중략
// rAF 재시작, 마지막 클릭으로 부터 3초가 경화하였을 때만 실행
if(timeSinceLastClick > 3000) setTimeout(() => requestAnimationFrame(carouselAnimate), 5000);
// 마지막 클릭 시간 업데이트
lastClickTime = now;
// 다음이면
}else if(to === 'navigate_next'){
// ... 중략
// rAF 재시작, 마지막 클릭으로 부터 3초가 경화하였을 때만 실행
if(timeSinceLastClick > 3000) setTimeout(() => requestAnimationFrame(carouselAnimate), 5000);
// 마지막 클릭 시간 업데이트
lastClickTime = now;
}
}
결론
캐러셀과 같이 자동적인 요소와 유저의 상호작용이 결합하여 동작하는 기능의 경우에는
유저의 반복 클릭 등 가능한 모든 상황을 가정하고 이에 대응할 수 있는 기능들을 적용해야 함을 배웠습니다.
'TIL' 카테고리의 다른 글
[240814 TIL] openai 이미지생성 (0) | 2024.08.15 |
---|---|
[240807 TIL] 모바일기기에서 개발해야할 때 (0) | 2024.08.07 |
[240422 TIL] 좋은 함수 (0) | 2024.04.22 |
[240421 WIL 1주차] 웹디자인, github, env (0) | 2024.04.21 |
[240419 TIL]첫 팀 프로젝트 회고 (1) | 2024.04.19 |