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을 사용하는 경우 타임스탬프 값을 사용하지 않습니다. 연결이 끊겼습니다. :)
이유
왜냐하면 Well 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));
}
이 문제를 수정하는 방법은 매우 간단합니다. startTime
및 now
를 보강하여 window.performance.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에 적용될 예정이므로 이미 이 콜백 매개변수를 활용하고 있다면 코드를 업데이트해야 합니다.