Animation 구현하기

웹에서 제공하는 window.requestAnimationFrame() 메서드를 이용하여 Animation을 구현할 수 있다. 해당 메서드에 수행하길 원하는 Animation을 콜백으로 넘겨주면, 브라우저가 Repaint하기 바로 전에 넘겨받은 Animation의 호출을 요청한다. 즉, 브라우저가 화면을 그릴 준비가 될때 마다, 넘겨 받은 콜백을 호출하여 효율적으로 Animation의 실행을 도와주는 메서드이다.

Window: requestAnimationFrame() method - Web API | MDN

window.requestAnimationFrame() 메서드의 콜백 횟수는 일반적으로 W3C 권장사항에 따라 디스플레이의 주사율과 일치한다. 즉 144hz의 디스플레이에서 해당 메서드는 1초에 144번 콜백을 호출한다.

원하는 FPS의 Animation

사용자의 디스플레이 주사율에 따라 Animation이 다르게 제공되는 것은 옳지 않다. 따라서 내가 원하는 FPS(frame per second) 를 정해 어느 디스플레이든 Animation이 똑같은 FPS로 제공되어야 한다. 10fps는 1초에 10프레임을 의미한다.

요즘 디스플레이는 아무리 낮아도 60hz, 즉 60fps의 주사율을 제공한다고 한다. 1초에 60번 호출, 약 16ms마다 requestAnimationFrame이 콜백을 호출한다. 해당 주사율의 디스플레이에서 내 Animation10fps로 실행하고 싶다면 어떻게 해야할까 ?

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마다 실행되고 있을것이다. 최초 실행시점인 then1000ms이라고 했을 때, 현재 실행시간 now1016ms, 1032ms, 1048ms… 일때마다 animate 함수가 실행된다. 실행될때마다 nowthen의 차이값인 delta값을 구해준다. delta에는 16, 32, 48… 의 값이 들어가게 될 것이다.

내가 animate함수가 실행 되길 원하는 시점은 최초 실행 시점에서 +interval한 시점(now1100ms)이다. 하지만 애초에 주사율에 맞춰서 animate함수가 실행되고 이 시점에 맞춰 now값을 가져 오기 때문에 정확히 1100msanimate함수를 실행 시킬 순 없다. 1100을 넘어가면서 가장 가까운 시점에 animate함수를 실행해 주어야 한다. 즉 dalta값이 interval값보다 커지는 시점에 원하는 애니메이션을 실행 시키도록 조건을 걸어준다.

원하는 애니메이션이 실행되면 then값을 재설정 해준다.

스크린샷 2023-07-21 오후 6.40.26.png