
requestAnimationFrame은 랜더링 최적화를 위해 사용하는 메소드로 함수 실행을 예약해준다. 함수는 리랜더링 직전에 실행되어 애니메이션 최적화를 할 수 있다.
requestAnimationFrame(애니메이션 함수)이렇게 작성하며 함수 실행을 예약한다. 이 때 함수에requestAnimationFrame(애니메이션 함수)를 넣어서 다시 예약을 하고 반복 실행이 된다. 콜백함수에 조건을 만들거나 종료 메소드(cancelAnimationFrame)를 직접 실행하여 종료할 수 있다.
requestAnimationFrame란?
리페인트 직전에 함수를 실행하여 애니메이션을 화면 랜더링 최적화를 할 수 있다.
값의 변경 로직을 반복적으로 실행해서 애니메이션을 구현하는데
setInterval()을 사용하여 반복하는 것과 무엇이 다를까?
| 기준 | setInterval | requestAnimationFrame |
|---|---|---|
| 동작 방식 | 일정한 시간 간격마다 함수를 반복 실행 | 브라우저의 렌더링 사이클에 맞춰 함수 실행 |
| 사용 사례 | 일정한 주기로 데이터 업데이트, 타이머 등 | 애니메이션, 화면 갱신과 관련된 작업 |
| 실행 주기 | 사용자가 지정한 시간 간격(밀리초 단위) | 보통 초당 60회(약 16.67ms), 디스플레이 주사율에 따름 |
| 성능 최적화 | 없음, 지정된 간격으로 계속 실행 | 브라우저 최적화에 따라 실행, 비활성 탭에서는 실행 감소 |
| 자원 사용 | 백그라운드에서도 지정된 간격으로 실행 | 비활성 탭이나 보이지 않는 요소에서 실행 줄임 |
| 시각적 부드러움 | 렌더링 사이클과 독립적, 불규칙할 수 있음 | 렌더링 사이클과 동기화, 시각적으로 부드러움 |
| 주요 단점 | 정밀한 타이밍 조절 어려움, 성능 문제 가능성 | 복잡한 애니메이션에서 코드 관리 필요 |
장점
예제
import React, { useState, useEffect } from "react";
function AnimatedComponent() {
const [posX, setPosX] = useState(-500);
const [animationFrameId, setAnimationFrameId] = useState(null);
useEffect(() => {
function animate() {
if (posX < 1000) {
setPosX(posX + 4);
} else {
setPosX(-500); // posX가 1000에 도달하면 -500으로 리셋
}
const id = requestAnimationFrame(animate);
setAnimationFrameId(id);
}
const id = requestAnimationFrame(animate);
setAnimationFrameId(id);
// 컴포넌트가 언마운트될 때 애니메이션 취소
return () => cancelAnimationFrame(animationFrameId);
}, [posX]);
const stopAnimation = () => {
cancelAnimationFrame(animationFrameId);
console.log("stop!");
};
return (
<div>
<button
onClick={stopAnimation}
style={{
width: "100px",
height: "50px",
position: "relative",
}}
>
Stop
</button>
<img
src="https://i.pinimg.com/originals/65/5d/2d/655d2da400a648abca600766a89deead.gif"
style={{
transform: `translateX(${posX}px)`,
width: "508px",
height: "381px",
backgroundColor: "blue",
position: "relative",
top: "100px",
}}
alt="Animated Element"
/>
</div>
);
}
export default AnimatedComponent;
종료
cancelAnimationFrame()
실행 조건을 설정하여 조건이 false일 때는 실행하지 않도록 하는 방법
종료 메소드를 동작해서 종료하는 방법
인자로 requestAnimationFrame() 의 반환 값을 넣어줘야 한다.