타이머는 항상 JavaScript 애니메이션의 핵심 기술이었습니다. 애니메이션 루프 작성의 핵심은 지연 시간이 얼마나 긴지 아는 것입니다. 한편으로는 루프 간격이 충분히 짧아서 다양한 애니메이션 효과가 부드럽게 표시되어야 하고, 반면에 루프 간격은 브라우저가 결과 변경 사항을 렌더링할 수 있을 만큼 충분히 길어야 합니다.
대부분의 컴퓨터 모니터의 새로 고침 빈도는 60Hz이며 이는 대략 초당 60회 다시 그리기에 해당합니다. 대부분의 브라우저는 다시 그리기 작업을 디스플레이의 다시 그리기 빈도 이하로 제한합니다. 그 빈도를 넘어서도 사용자 경험은 향상되지 않기 때문입니다. 따라서 가장 부드러운 애니메이션을 위한 최적의 루프 간격은 1000ms/60이며 이는 대략 16.6ms와 같습니다.
setTimeout 및 setInterval의 문제점은 정확하지 않다는 것입니다. 내부 작동 메커니즘은 시간 간격 매개변수가 실제로 실행을 대기하기 위해 브라우저 UI 스레드 대기열에 애니메이션 코드를 추가하는 시간을 지정한다고 결정합니다. 대기열 앞에 다른 작업이 추가된 경우 애니메이션 코드는 이전 작업이 완료될 때까지 기다렸다가 실행해야 합니다.
requestAnimationFrame은 최상의 그리기 효율성을 유지하기 위해 시스템 시간 간격을 사용합니다. 간격이 너무 짧기 때문에 과도한 그리기가 발생하거나 오버헤드가 증가하지 않으며 간격이 너무 길어서 애니메이션이 멈추거나 부드럽지 않게 됩니다. 다양한 웹 페이지 애니메이션 효과를 얻을 수 있습니다. 시스템 리소스를 절약하고 시스템 성능을 향상하며 시각 효과를 향상시키는 통합 새로 고침 메커니즘이 있습니다.
특징requestAnimationFrame 메소드는 콜백을 매개변수로 받으며, 콜백 함수는 현재 requestAnimationFrame()에 의해 정렬된 콜백 함수가 트리거되는 시간을 나타내는 DOMHighResTimeStamp 매개변수로 전달됩니다. 반환 값은 콜백 목록의 고유 식별자를 나타내는 요청 ID입니다. 이 값을 window.cancelAnimationFrame()에 전달하여 콜백 함수를 취소할 수 있습니다.
requestID = window.requestAnimationFrame(콜백);
이 API를 사용하면 다음 번 다시 렌더링하는 동안 특정 코드를 실행하여 짧은 시간 내에 많은 수의 리플로우가 발생하는 것을 방지할 수 있습니다.
예를 들어, 페이지 스크롤 이벤트(스크롤)의 콜백 함수는 이 API를 사용하는 데 매우 적합하며 다음 다시 렌더링할 때까지 콜백 작업을 연기합니다. 그러나 requestAnimationFrame은 콜백 함수를 관리하지 않습니다. 즉, 콜백이 실행되기 전에 동일한 콜백 함수로 requestAnimationFrame을 여러 번 호출하면 콜백이 동일한 프레임에서 여러 번 실행됩니다. 가장 간단한 방법은 조절 기능을 사용하여 이 문제를 해결하는 것입니다. 또는 requestAnimationFrame의 대기열에 동일한 콜백 함수를 하나만 포함하는 방법을 찾을 수 있습니다.
let ScheduledAnimationFrame = false;document.body.onscroll = () => { if (scheduledAnimationFrame) return; ScheduledAnimationFrame = true; window.requestAnimationFrame(() => { ScheduledAnimationFrame = false; // 작업 수행 });};
물론 최고의 애플리케이션 시나리오는 여전히 성능을 크게 최적화할 수 있는 프레임 애니메이션입니다.
면접 질문 인터페이스에 갇히지 않고 수만 개의 데이터 조각을 렌더링하는 방법이 질문은 페이지를 차단하지 않고 데이터를 렌더링하는 방법을 조사합니다. 즉, 수만 개의 항목을 한 번에 렌더링할 수 없지만 DOM의 일부를 한 번에 렌더링해야 합니다. 그런 다음 requestAnimationFrame을 통해 16ms마다 새로 고칠 수 있습니다.
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width,initial-scale=1.0> <meta http-equiv=X-UA -호환 가능한 콘텐츠=ie=edge> <title>문서</title></head><body> <ul>제어</ul> <script> setTimeout(() => { // 100,000개의 데이터를 삽입합니다. const total = 100000 // 한 번에 20개씩 삽입합니다. 성능이 좋지 않다고 생각되면 const one = 20 // 데이터를 렌더링하는 데 몇 번 걸릴까요? const loopCount = total / Once let countOfRender = 0 let ul = document.querySelector(ul); function add() { // 성능 최적화, 삽입 시 역류가 발생하지 않음 const 조각 = document.createDocumentFragment() for (let i = 0; i < 한 번; i++) { const li = document.createElement(li); li.innerText = Math.floor(Math.random() * total); ul.appendChild(fragment); 1; 루프(); } 함수 루프() { if (countOfRender < loopCount) { window.requestAnimationFrame(추가) } 루프() }, 0);호환성
일부 오래된 브라우저는 이 API를 지원하지 않습니다. 이 API를 사용하려면 이 방법을 사용자 정의하고 창 아래에 마운트할 수 있습니다.
(function() { var lastTime = 0; var Vendors = ['webkit', 'moz']; for(var x = 0; x < Vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback) { var currTime = new Date().getTime(); 0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) };}())
위의 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.