requestAnimationFrame
를 사용해 왔다면 페인트가 화면의 새로고침 속도에 동기화되어 최대한 높은 충실도의 애니메이션을 볼 수 있었습니다. 또한 사용자가 다른 탭으로 전환할 때 CPU 팬 소음과 배터리 전력을 절약할 수 있습니다.
하지만 API의 일부가 변경될 예정입니다. 콜백 함수에 전달되는 타임스탬프가 일반적인 Date.now()
유형의 타임스탬프에서 페이지가 열렸을 때부터의 부동 소수점 밀리초의 고해상도 측정값으로 변경됩니다. 이 값을 사용하는 경우 아래 설명에 따라 코드를 업데이트해야 합니다.
명확히 말씀드리자면 다음과 같은 내용입니다.
// assuming requestAnimationFrame method has been normalized for all vendor prefixes..
requestAnimationFrame(function(timestamp){
// the value of timestamp is changing
});
여기에 제공된 일반적인 requestAnimFrame
shim을 사용하는 경우 타임스탬프 값을 사용하지 않는 것입니다. 걱정하지 마세요. :)
이유
왜냐하면 rAF를 사용하면 이상적인 60fps를 얻을 수 있으며 60fps는 프레임당 16.7ms로 변환됩니다. 하지만 정수 밀리초로 측정하면 관찰하고 타겟팅하려는 모든 항목에 대해 1/16의 정밀도가 적용됩니다.

위에서 볼 수 있듯이 파란색 막대는 새 프레임을 페인트하기 전에 모든 작업을 완료해야 하는 최대 시간을 나타냅니다 (60fps 기준). 16개가 넘는 작업을 실행하고 있을 수 있지만 정수 밀리초를 사용하면 이러한 매우 큰 증분으로만 예약하고 측정할 수 있습니다. 충분하지 않습니다.
고해상도 타이머는 훨씬 더 정확한 수치를 제공하여 이 문제를 해결합니다.
Date.now() // 1337376068250
performance.now() // 20303.427000007
고해상도 타이머는 현재 Chrome에서 window.performance.webkitNow()
로 사용할 수 있으며, 이 값은 일반적으로 rAF 콜백에 전달된 새 인수 값과 같습니다. 사양이 표준을 통해 더 진행되면 메서드의 접두사가 삭제되고 performance.now()
를 통해 사용할 수 있게 됩니다.
또한 위의 두 값은 수십 배 차이가 있습니다. performance.now()
는 특정 페이지 로드가 시작된 후 경과한 부동 소수점 밀리초 (구체적으로는 performance.navigationStart
)를 나타냅니다.
사용 중
이 설계 패턴을 사용하는 애니메이션 라이브러리가 주요 문제입니다.
function MyAnimation(duration) {
this.startTime = Date.now();
this.duration = duration;
requestAnimFrame(this.tick.bind(this));
}
MyAnimation.prototype.tick = function(time) {
var now = Date.now();
if (time > now) {
this.dispatchEvent("ended");
return;
}
...
requestAnimFrame(this.tick.bind(this));
}
이 문제를 해결하는 수정사항은 매우 간단합니다. window.performance.now()
를 사용하도록 startTime
및 now
를 확장합니다.
this.startTime = window.performance.now ?
(performance.now() + performance.timing.navigationStart) :
Date.now();
이는 매우 순진한 구현으로, 접두사가 있는 now()
메서드를 사용하지 않으며 IE8에 없는 Date.now()
지원을 가정합니다.
기능 감지
위의 패턴을 사용하지 않고 어떤 종류의 콜백 값이 반환되는지 확인하려면 다음 기법을 사용하세요.
requestAnimationFrame(function(timestamp){
if (timestamp < 1e12){
// .. high resolution timer
} else {
// integer milliseconds since unix epoch
}
// ...
if (timestamp < 1e12)
를 확인하는 것은 처리 중인 숫자의 크기를 확인하는 빠른 테스트입니다. 기술적으로는 웹페이지가 30년 동안 계속 열려 있는 경우에만 거짓양성이 발생할 수 있습니다. 하지만 정수로 올림 처리되는 것이 아니라 부동 소수점 수인지 테스트할 수는 없습니다. 충분한 고해상도 타이머를 요청하면 어느 시점에서는 정수 값을 반환할 수밖에 없습니다.
이 변경사항은 Chrome 21에서 적용될 예정이므로 이미 이 콜백 매개변수를 사용하고 있다면 코드를 업데이트하시기 바랍니다.