Javascript로 무한슬라이드를 구현하는 과정에서
setInterval()을 사용했습니다
브라우저를 켜놓고 보면 아주 작동이 잘합니다.
그런데 다른 브라우저 탭을 열어놓고 다시 들어가보니 다음과 같은 상황이 발생...
setInterval()함수를 통해 불려진 콜백이 계속 쌓여있다가 브라우저로 다시 돌아오는 순간 한번에 실행된다.
굳이 이런 상황을 원하는게 아니기에 이를 해결하기 위해 찾아본 결과,
requestAnimationFrame API를 이용하면 해결이 가능하다.
자세한 내용과 장점 등은 아래의 블로그 주인분께서 정말 자세히 설명.
https://inpa.tistory.com/entry/%F0%9F%8C%90-requestAnimationFrame-%EA%B0%80%EC%9D%B4%EB%93%9C
구체적인 구현 코드
Javascript
const slideContainer = document.querySelector(".slide-content");
const containerLength = slideContainer.children.length;
const slideItemWidth = slideContainer.children[0].offsetWidth;
let slideCount = 0;
function slideBanner() {
const clonedChildren = slideContainer.children;
slideContainer.style.transition = "1s ease-out";
slideContainer.style.left = -slideItemWidth * (slideCount) + "px";
slideCount++;
if (slideCount % containerLength == 0) {
for (let i = 0; i < containerLength; i++) {
slideContainer.append(clonedChildren[i].cloneNode(true))
}
}
}
// requestAnimationFrame 관련은 아래부터
const interval = 1000;
let lastTime = 0;
function animate(timestamp, isClicked = false) {
if (isClicked) {
lastTime = timestamp;
}
elapsed = timestamp - lastTime;
if (elapsed >= interval) {
slideBanner();
lastTime = timestamp;
}
raf = requestAnimationFrame(animate);
}
let raf = requestAnimationFrame(animate);
slideContainer.addEventListener("click", function () {
slideBanner();
raf = requestAnimationFrame(timestamp => animate(timestamp, true));
});
* 주의 사항
- clearInterval()과는 약간 다르게 동작
기본적으로 requestAnimationFrame을 쓰는 방법은,
animation을 적용한 함수 funtion animate() 가 있다고 하면
let raf = requestAnimationFrame(animate); 와 같이 실행하고
일시적으로 멈출때 아래와 같이 사용한다.
cancelAnimationFrame(raf);
clearInterval()과 같은 방식으로 작동할 것이라 생각하고 원래는 아래와 같이 작성했었다.
slideContainer.addEventListener("click", function () {
cancelAnimationFrame(raf);
slideBanner();
raf = requestAnimationFrame(animate);
});
그러면 클릭했을 때 raf가 초기화 되었다가
다시 raf=requestAnimationFrame(animate)를 호출한 부분부터 작동할 것이라 생각했다.
그러나 clearInterval()과는 약간 다른 방식으로 작동한다.
requestFrameAnimation은 timestamp를 인자로 기본으로 넘겨주는데,
cancelAnimationFrame(raf) 이후에
다시 raf = requestAnimationFrame(animate);를 실행시키는 상황에서
animate function 안에서 console.log(timestamp)를 찍어보면,
timestamp가 지워지지 않고 계속 누적해서 쌓이고 있음을 확인할 수 있다.
즉, cancelAnimationFrame 기능으로 일시적인 멈춤을 주는 것이지,
초기화 하는 것처럼 기능하지 않는 것이다.
이 때문에, animate 안에 click의 상황인지 아닌지를 이용할 수 있게 isClicked 인자를 넘겨서 판단하고,
slideContainer의 addEventListener 안에서 raf에 requestAnimationFrame을 재지정할 때,
raf = requestAnimationFrame(timestamp => animate(timestamp, isClicked=true));
위와 같이 timestamp와 함께 isClicked=true를 넘겨주는 방식을 이용했다.
elapsed가 지정해준 interVal 이상이 될 때 slideBanner()가 작동하므로
isClicked=true인 경우에 elapsed = 0 이 될 수 있도록 lastTime = timeStamp로 해준다.
'Javascript' 카테고리의 다른 글
Javascript: 클라이언트 단에서의 대용량 데이터 처리 성능 이슈 개선 # 비동기처리 # Chunk # requestAnimationFrame (rAF) (2) | 2024.12.13 |
---|---|
Javascript: arrow function (0) | 2024.05.22 |
Javascript: slide # 무한 슬라이드 (0) | 2023.09.10 |
Javascript: Parsing HTML #select #checkbox #radio (0) | 2023.03.31 |
Javascript: new Date # 날짜 (0) | 2023.03.27 |