웹에서 제공하는 window.requestAnimationFrame()
메서드를 이용하여 Animation
을 구현할 수 있다. 해당 메서드에 수행하길 원하는 Animation
을 콜백으로 넘겨주면, 브라우저가 Repaint
하기 바로 전에 넘겨받은 Animation
의 호출을 요청한다. 즉, 브라우저가 화면을 그릴 준비가 될때 마다, 넘겨 받은 콜백을 호출하여 효율적으로 Animation
의 실행을 도와주는 메서드이다.
Window: requestAnimationFrame() method - Web API | MDN
window.requestAnimationFrame()
메서드의 콜백 횟수는 일반적으로 W3C 권장사항에 따라 디스플레이의 주사율과 일치한다. 즉 144hz
의 디스플레이에서 해당 메서드는 1초에 144번 콜백을 호출한다.
사용자의 디스플레이 주사율에 따라 Animation
이 다르게 제공되는 것은 옳지 않다. 따라서 내가 원하는 FPS(frame per second)
를 정해 어느 디스플레이든 Animation
이 똑같은 FPS
로 제공되어야 한다. 10fps
는 1초에 10프레임을 의미한다.
요즘 디스플레이는 아무리 낮아도 60hz
, 즉 60fps
의 주사율을 제공한다고 한다. 1초에 60번 호출, 약 16ms
마다 requestAnimationFrame
이 콜백을 호출한다. 해당 주사율의 디스플레이에서 내 Animation
을 10fps
로 실행하고 싶다면 어떻게 해야할까 ?
requestAnimationFrame
이 실행되는 최초시점 시점(then
)과, 콜백이 호출되는 시점(now
)의 값을 원하는 fps에 따른 second값(interval
)과 비교해 주면 된다.
const interval = 1000 / 10
let now, delta;
let then = Date.now();
function animate() {
window.requestAnimationFrame(animate);
now = Date.now();
delta = now - then;
if(delta < interval) return;
// 원하는 애니메이션 실행
then = now - (delta % interval);
}
animate();
주사율에 따라 animate
함수는 1초에 60번, 즉 16ms
마다 실행되고 있을것이다. 최초 실행시점인 then
을 1000ms
이라고 했을 때, 현재 실행시간 now
가 1016ms
, 1032ms
, 1048ms
… 일때마다 animate
함수가 실행된다. 실행될때마다 now
와 then
의 차이값인 delta
값을 구해준다. delta
에는 16, 32, 48… 의 값이 들어가게 될 것이다.
내가 animate
함수가 실행 되길 원하는 시점은 최초 실행 시점에서 +interval
한 시점(now
가 1100ms
)이다. 하지만 애초에 주사율에 맞춰서 animate
함수가 실행되고 이 시점에 맞춰 now
값을 가져 오기 때문에 정확히 1100ms
에 animate
함수를 실행 시킬 순 없다. 1100을 넘어가면서 가장 가까운 시점에 animate
함수를 실행해 주어야 한다. 즉 dalta
값이 interval
값보다 커지는 시점에 원하는 애니메이션을 실행 시키도록 조건을 걸어준다.
원하는 애니메이션이 실행되면 then
값을 재설정 해준다.