Таймеры всегда были основной технологией анимации JavaScript. Ключом к написанию цикла анимации является знание продолжительности времени задержки. С одной стороны, интервал цикла должен быть достаточно коротким, чтобы различные эффекты анимации выглядели плавно, с другой стороны, интервал цикла должен быть достаточно длинным, чтобы браузер мог отображать полученные изменения;
Частота обновления большинства компьютерных мониторов составляет 60 Гц, что примерно соответствует 60 перерисовкам в секунду. Большинство браузеров ограничивают операции перерисовки частотой, превышающей частоту перерисовки дисплея, поскольку даже за пределами этой частоты взаимодействие с пользователем не улучшится. Поэтому оптимальный интервал цикла для максимально плавной анимации — 1000мс/60, что примерно равно 16,6мс.
Проблема с setTimeout и setInterval заключается в том, что они неточны. Их внутренний операционный механизм определяет, что параметр интервала времени на самом деле просто указывает время добавления кода анимации в очередь потоков пользовательского интерфейса браузера для ожидания выполнения. Если в начало очереди были добавлены другие задачи, код анимации должен дождаться завершения предыдущей задачи, прежде чем выполнять ее.
requestAnimationFrame использует системный временной интервал для обеспечения максимальной эффективности отрисовки. Это не приведет к перерисовке и увеличению накладных расходов, поскольку интервал слишком короткий. Это также не приведет к зависанию и неплавности анимации, поскольку интервал слишком длинный. различные эффекты анимации веб-страниц. Существует унифицированный механизм обновления для экономии системных ресурсов, повышения производительности системы и улучшения визуальных эффектов.
ФункцииМетод requestAnimationFrame принимает обратный вызов в качестве параметра, а функция обратного вызова будет передана в параметре DOMHighResTimeStamp, указывающем время, когда срабатывает функция обратного вызова, отсортированная в данный момент с помощью requestAnimationFrame(). Возвращаемое значение — это идентификатор запроса, который представляет собой уникальный идентификатор в списке обратных вызовов. Это значение можно передать в window.cancelAnimationFrame(), чтобы отменить функцию обратного вызова.
requestID = window.requestAnimationFrame(обратный вызов);
Используя этот API, определенные коды могут быть выполнены во время следующего повторного рендеринга, чтобы избежать запуска большого количества перекомпоновок за короткий период времени.
Например, для использования этого API очень подходит функция обратного вызова события прокрутки страницы (прокрутки), откладывающая операцию обратного вызова до следующего повторного рендеринга. Однако следует отметить, что requestAnimationFrame не управляет функциями обратного вызова, то есть вызов requestAnimationFrame с одной и той же функцией обратного вызова несколько раз до выполнения обратного вызова приведет к выполнению обратного вызова несколько раз в одном и том же кадре. Самый простой способ — использовать функцию регулирования для решения этой проблемы, или вы можете найти способ иметь только одну и ту же функцию обратного вызова в очереди requestAnimationFrame:
let ScheduledAnimationFrame = false;document.body.onscroll = () => { if (scheduledAnimationFrame) return;
Конечно, лучшим сценарием приложения по-прежнему является покадровая анимация, которая позволяет значительно оптимизировать производительность.
Вопросы для интервью Как визуализировать десятки тысяч фрагментов данных, не застревая в интерфейсеВ этом вопросе рассматривается, как визуализировать данные без блокировки страницы. То есть вы не можете визуализировать десятки тысяч элементов одновременно, а должны визуализировать часть DOM сразу. Затем вы можете обновлять его каждые 16 мс через requestAnimationFrame.
<!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 -Compatible content=ie=edge> <title>Document</title></head><body> <ul>Control</ul> <script> setTimeout(() => { // Вставьте 100 000 фрагментов данных const total = 100000 // Вставьте 20 фрагментов за раз. Если вы чувствуете, что производительность низкая, уменьшите const один раз = 20 // Сколько раз потребуется отрисовка данных const locount = 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); фрагмент.appendChild(li); ul.appendChild(fragment); 1; цикл(); } функция цикла() { if (countOfRender <loopCount) { window.requestAnimationFrame(add); цикл() }, 0 </script></body></html>совместимость
Некоторые старые браузеры не поддерживают этот API. Чтобы использовать этот API, вы можете настроить этот метод и смонтировать его под окном:
(function() { varlastTime = 0; varvendors = ['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(); var timeToCall = Math.max( 0, 16 - (currTime - LastTime)); var id = window.setTimeout(function() { callback(currTime +)); timeToCall); }, timeToCall); LastTime = currTime + timeToCall; return id; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) {clearTimeout(id);}());
Выше приведено все содержание этой статьи. Я надеюсь, что она будет полезна для изучения всеми. Я также надеюсь, что все поддержат сеть VeVb Wulin.