>  기사  >  웹 프론트엔드  >  완화 기능 requestAnimationFrame은 브라우저 애니메이션을 더 잘 구현합니다_기본 지식

완화 기능 requestAnimationFrame은 브라우저 애니메이션을 더 잘 구현합니다_기본 지식

WBOY
WBOY원래의
2016-05-16 17:47:22971검색

requestAnimationFrame 함수는 easing 함수를 작성하는 데 사용됩니다. 이전에 배운 적이 있지만 항상 잘 이해되지 않는 것 같아서 학습 목적으로 외국인이 쓴 기사를 번역했습니다. 공유.

requestAnimationFrame이 무엇인가요?
과거에는 애니메이션을 만들 때 밀리초마다 변경 사항을 적용하는 타이머가 필요했습니다. 이제 좋은 소식이 있습니다. 브라우저 제조업체는 애니메이션 전용 메서드인 requestAnimationFrame()을 제공하기로 결정했으며 이는 브라우저 수준에서 더욱 효과적으로 최적화될 수도 있습니다. 그러나 이는 애니메이션을 위한 기본 API일 뿐이며, DOM 요소의 스타일 변경을 기반으로 하지 않으며, 캔버스나 WebGL을 기반으로 하지도 않습니다. 따라서 구체적인 애니메이션 세부 사항을 직접 작성해야 합니다.

왜 사용해야 하나요?
n개의 애니메이션이 동시에 실행되는 경우 브라우저는 원래의 N번의 리플로우를 최적화하고 1번으로 다시 그려서 고품질의 애니메이션을 구현할 수 있습니다. 예를 들어 JS 기반 애니메이션, CSS 기반 전환 또는 SVG SMIL Plus가 있습니다. 브라우저의 탭에서 이러한 애니메이션이 실행되고 있는데 다른 탭으로 전환하거나 간단히 최소화하면 볼 수 없으면 브라우저가 애니메이션을 중지합니다. 이는 CPU, GPU 및 메모리 소비량이 적어 배터리 수명이 훨씬 길어진다는 것을 의미합니다.

어떻게 사용하나요?

코드 복사 코드는 다음과 같습니다.

// setTimeout이 있는 shim 레이어 fallback
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window .msRequestAnimationFrame |
function(/* 함수 */ 콜백, /* DOMElement */ 요소){
window.setTimeout(callback, 1000 / 60)
})() ;
// 사용법:
// setInterval(render, 16) 대신 ....
(function animloop(){
render();
requestAnimFrame(animloop, element) ;
})();

참고: 사양이 계속 변경되고 사양에 영향을 받고 싶지 않기 때문에 여기서는 "requestAnimFrame"을 사용했습니다.
requestAnimationFrame API

코드 복사 코드는 다음과 같습니다.
window.requestAnimationFrame( function(/ * time */ time){
// time ~= new Date // 유닉스 시간
}, /* 선택적 경계 요소 */ elem)

Give Chrome 우선 및 Firefox 버전

코드 복사 코드는 다음과 같습니다.
window.mozRequestAnimationFrame( [콜백]) ; // Firefox
window.webkitRequestAnimationFrame(callback[, element]); // Chrome

매개변수:
콜백: (FF 선택 사항, Chrome 필요)
다음 repaint에 의해 호출되는 함수, 함수의 첫 번째 매개변수는 현재 시간
요소: (FF 없음)
바꿔 말하면 실제로는 캔버스이고 '그림'은 애니메이션입니다. (전체 애니메이션을 시각적으로 제한하는 요소) 캔버스 및 WebGL의 경우 요소입니다. DOM 노드의 경우 이를 무시할 수 있으며, 이를 약간 최적화하려면 매개변수를 전달할 수도 있습니다.


신뢰할 수 있는가요? 이제 Webkit 구현(Nightly Safari 및 Chrome Dev Channel에서 사용 가능)과 Mozilla 구현(FF4에서 사용 가능) 간에는 몇 가지 차이점이 있으며 Mozilla 구현에는 버그가 있습니다. 실제로 FF 애니메이션의 프레임 수는 1000/(16 N) fps로 계산됩니다. 여기서 N은 콜백 실행 시간(밀리초)입니다. 콜백 실행 시간이 1000ms인 경우 최고 프레임 속도는 1fps에 불과합니다. 콜백 실행 시간이 1ms라면 프레임 속도는 거의 60fps입니다. 이 버그는 확실히 수정될 것입니다. 아마도 다음 버전의 FF4에서는 수정될 것입니다. Chrome10에는 시간 매개변수(m11에 추가되었습니다. m11이 무엇인지 묻고 싶습니다.)가 없으며, FF에는 현재 요소 매개변수가 없습니다.
Firefox에서 버그를 살펴본 결과 아마도 다음과 같은 의미일 것입니다.
콜백 실행 시간이 1000/60밀리초 미만이더라도 FF의 mozRequestAnimationFrame()은 60fps에 도달할 수 없습니다. 예:

코드 복사 코드는 다음과 같습니다.
function callback(time) {
window.mozRequestAnimationFrame(콜백);
doWork()
}


doWork()가 1000/60밀리초가 걸리는 경우 프레임 속도는 약 30fps이고 동일한 애니메이션이 setTimeout(콜백, 16)을 사용하는 경우 프레임 속도는 60fps입니다. 콜백이 실행되기 시작한 후 16ms가 아닌 콜백이 실행된 후 약 16ms 후에 항상 콜백이 다시 실행되기 시작하는 것 같습니다. 후자이고 계산 속도가 충분히 빠르면 60fps 프레임을 생성할 수 있습니다.
표준 컨트롤이라면 포털이 여기 있습니다



더 이상 고민하지 말고 클래식 애니메이션 기능부터 시작해 보세요:
코드 복사 코드는 다음과 같습니다.

function animate(element, name, from, to, time) {
time = 시간 || 800; //기본값 0.8초
var style = element.style,
latency = 60, //60ms마다 변경
count = 시간/대기 시간, //변경 횟수
step = Math.round((to - from) / count), //각 단계의 변화량
now = from
function go() {
count--; 🎜>now = count ? now step: to;
style[name] = 이제 'px'
if (count) {
setTimeout(go, Latency)
}
style [name] = from 'px';
setTimeout(go,latency);
}


단위는 px로만 설정할 수 있습니다. 스타일을 수정하세요. 함수 구현 관점에서만 보면 매우 고전적인 애니메이션 개념이라고 할 수 있습니다. 기본 로직은 다음과 같은 부분으로 구성됩니다.
시작점 값과 끝점 값을 가져오고, 애니메이션에 소요되는 시간과 각 감지 지연 시간 요구 사항 간의 간격, 값 변경 횟수 및 각 변경 단계의 양을 계산합니다.
다음 감지로 이동하려면 setTimeout(fn, 대기 시간)을 활성화하세요.

다음 감지에서는 속성 단계를 한 번 설정하고 애니메이션이 아직 종료되지 않은 경우 2단계로 돌아가서 다음 감지를 계속합니다.
이 함수는 매우 잘 작동하며 수천 개의 사이트와 시스템에 서비스를 제공합니다. 실제로 jQuery의 animate 함수의 핵심은 setInterval 함수에 지나지 않습니다.
그러나 현재 시스템의 복잡성이 꾸준히 증가함에 따라 애니메이션 효과가 점점 더 많아지고 애니메이션의 부드러움에 더 많은 관심이 집중되어 위 기능에 몇 가지 문제가 발생합니다. 예를 들어 100개의 애니메이션 효과가 동시에 켜지면 위 함수에 따르면 100개의 타이머가 동시에 실행될 것이 분명하며 이러한 타이머 간의 스케줄링이 성능에 약간의 영향을 미칠 것입니다. 일반적인 환경에서는 이러한 작은 효과가 중요하지 않지만 애니메이션과 같이 유창성에 대한 요구 사항이 높은 환경에서는 미묘한 영향으로 인해 나쁜 사용자 경험이 발생할 수 있습니다.

이러한 상황에서 일부 개발자는 타이머를 사용하여 애니메이션 프레임을 트리거하고 다양한 애니메이션이 이러한 프레임을 각 프레임에 등록하는 통합 프레임 관리를 기반으로 하는 애니메이션 프레임워크를 개발했습니다. 타이머 스케줄링에 따른 오버헤드를 줄일 수 있다는 장점이 있지만, 애니메이션 프레임워크 개발자의 경우 프레임 모니터링을 위한 통합된 프레임 관리 및 API를 개발하고 유지 관리해야 합니다.


직접 브라우저 지원
결국 브라우저 제조업체는 이것이 실제로 수행될 수 있음을 발견했으며 브라우저 수준에 따라 더 많은 최적화가 있을 수 있습니다. 예를 들면 다음과 같습니다. 한 설문조사에서 DOM에 대한 모든 작업에 대해 레이아웃과 페인트는 한 번만 수행됩니다.
애니메이션 요소가 숨겨져 있으면 페인트가 수행되지 않습니다.
이에 따라 브라우저에서는 requestAnimationFrame이라는 API를 출시하기 시작했습니다. 이 함수에 대해서는 MDC의 관련 페이지에 간단히 설명하면 이 함수를 사용하는 방법에는 두 가지가 있습니다.
requestAnimationFrame 함수를 호출합니다. 콜백 매개변수를 전달하면 다음 애니메이션 프레임에서 콜백이 호출됩니다.
매개변수를 전달하지 않고 이 함수를 직접 호출하면 다음 프레임이 트리거될 때 window.onmozbeforepaint 이벤트가 동시에 트리거됩니다. 이 이벤트를 등록하면 애니메이션을 적용할 수 있습니다.

두 번째 방법은 Firefox 자체 이벤트에 의존하며 beforepaint 이벤트가 아직 표준에 진입하지 않았으므로 첫 번째 방법을 사용하지 않는 것이 좋습니다. 이때 애니메이션 로직은 다음과 같습니다.
현재 시간 startTime을 애니메이션이 시작되는 시간으로 기록합니다.
콜백 함수로 다음 프레임을 요청합니다.
다음 프레임이 트리거되면 콜백 함수의 첫 번째 매개변수는 현재 시간이며, 이 값을 startTime과 비교하여 시간 간격 elapseTime을 결정합니다.
ellapseTime이 미리 설정된 애니메이션 시간을 초과했는지 여부를 판단합니다. 초과하는 경우 애니메이션을 종료합니다.
애니메이션 속성 변경의 차이를 계산한 다음 ellapseTime = Difference / time * ellapseTime 동안 변경해야 하는 단계의 양을 결정합니다.
지금으로 변경되어야 하는 Math.round(단계에서) 위치를 계산하고 스타일을 다시 할당합니다.
계속해서 다음 프레임을 요청하세요.


새로운 애니메이션 기능
다음은 새로운 애니메이션 기능입니다.

코드 복사 코드는 다음과 같습니다.

function animate(element, name, from, to, time) {
time = time || 800; // 기본값 0.8초
var style = element.style,
startTime = new Date;
function go(timestamp) {
var Progress = timestamp - startTime;
if (progress >= Duration) {
style[name] = to 'px'; return;
}
var now = (to - from) * (진행률/기간)
style[name] = now.toFixed()
requestAnimationFrame(go); 🎜>}
style[name] = from 'px';
requestAnimationFrame(go);
}


이 시점에서 한 가지 문제가 남습니다. 모든 브라우저가 requestAnimationFrame 기능을 지원하는 것은 아니므로 간단하게 수정해 보세요.
Firefox의 특성에 따르면 mozRequestAnimationFrame이 제공하는 최고 FPS는 60이며 각 프레임의 계산 시간에 따라 조정됩니다. 예를 들어 각 프레임을 계산하는 데 1초가 걸린다면 1FPS만 제공합니다. 애니메이션 효과.
Chrome의 상위 버전에서도 webkitRequestAnimationFrame이라는 이 기능을 구현합니다. 향후 Opera의 oRequestAnimationFrame과 IE의 msRequestAnimationFrame이 있을 것으로 예상되므로 간단한 호환성 프로세스는 다음과 같습니다.


requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame || .webkitRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback) { setTimeout(callback, 1000 / 60);
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.