Комментарии 6
За статью спасибо, было интересно почитать.
Вот этот момент я не совсем понял:
Даже если с точки зрения пользователя страница "подвисает", могут быть периоды, когда браузер находится в режиме ожидания.
Если браузер простаивает, почему страница для юзера может подвиснуть?
Возможно имелось ввиду, что если на странице производится какие-то сложные изменения макета с просадкой фреймрейта, то все равно будут моменты с периодами ожидания. То есть даже если вычисления в колбеке requestAnimationFrame
, по каким-то причинам длятся несколько фреймов, то после окончательного вычисления кадра, и до вызова следующего requestAnimationFrame
, все равно пройдет некоторое время, так как их вызовы этих колбеков синхронизируются через vsync. Собственно, время после вычисления кадра и до непосредственного вывода результата, можно дополнительно загрузить полезной работой.
рендеринг виртуальных фигур полностью контролируется пользователем — при нажатии кнопки
Render
пользователь осознает возможные негативные последствия, о которых говорилось выше, и готов к ним (снижение производительности является ожидаемым)
Пример показался немного странным. По сути получается, что на момент вызова колбека, уже есть вычисленный макет текущего кадра, что позволяет произвести оценку того, какое влияние оказывает изменения в DOM, на производительность рендера. Таким образом можно добавлять по столько элементов, чтобы пользователь не чувствовал заметных просадок по производительности. Просто какой смысл в пакетном добавлении элементов, если это полностью зависит от действий пользователя, которому необходимо смиряться с негативными последствиями этих действий. А данная функция, наоборот позволяет более точно контролировать эти негативные последствия, без участия со стороны пользователя.
За статью спасибо. Не знал об этой функции, и уже примерно представляю, что и где смогу улучшить с ее помощью.
Заметке не хватает очень важных акцентов, ради которых эта заметка и должна была бы писаться. Более того, из последующих примеров видно, что автор не до конца прочувствовал что для чего и как работает.
requestAnimationFrame
основная задача requestAnimationFrame заключается не в том, чтобы Вы писали с его помощью анимации. Это следствие. Его основная задача, предоставить программисту сигнал, когда он может, без боязни просадить производительность, работать с DOM.
Дело в том, что даже чтение некоторых свойств DOM дерева может приводит к полной перерисовке макета в окне браузера. Что, как мы понимаем, является ОЧЕНЬ дорогой операцией.
Я хочу подчеркнуть - даже чтение некоторых свойств DOM. Еще раз. Не модификации DOM. А чтении.
Для наиболее любознательных рекомендую гуглить DOM Reflow. Или начать с этой ссылки https://gist.github.com/paulirish/5d52fb081b3570c81e3a где популярно разбирается этот процесс, и причины, которые приводят к серьезным потерям производительности.
Так вот именно requestAnimationFrame является той волшебной палочкой, которая дает нам отмашку, когда мы безбоязненно можем вертеть нашим DOM как нам хочется.
requestIdleCallback
Предоставляет на много больше чем то о чем Вы написали. И, что самое главное, при правильной организации нашего кода, время, предоставляемое для callback может измерятся десятками миллисекунд.
Изменять DOM внутри этого callback нельзя не по той причине, что нам выдали слишком мало времени. А по той причине, что requestIdleCallback может сработать в любой момент времени. Даже тогда, когда наша неаккуратная работа с DOM может привести к постоянным Reflow. И именно по этой причине в этом апи не рекомендуется работать с DOM, если, конечно, вы не понимаете что делаете. А рекомендуется организовывать очередь, для следующего срабатывания requestAnimationFrame
Safari
И автор совершенно прав. Safari это IE современности. Я очень не завидую проектам, которые обязаны его поддерживать. Потому как этот браузер не просто IE современного мира, он значительно хуже. Так как мейнтенеры, не просто отказывают в поддержке большого количества таких вкусных вещей, но и не дают им никаких альтернатив, возвращая нас во время 2000 годов, с хаками вида setTimeout( func, 0);
У вашего комментария почему-то нет плюсов, надеюсь, другие читающие смогут это исправить.
А меня, как начинающего понимать несомненную пользу rAF, в контексте всего прочитанного интересует сейчас такой вопрос: как однозначно понять, когда он необходим, а когда - бесполезен? Есть ли смысл использовать его там, где перерисовка DOM теоретически происходит значительно реже, чем перерисовка кадров? Например вот так:
const recalcWidth = (time) => {
let incrW = diffWidth*time/trackDuration;
if (leftElement) {
leftWidth = leftWidth - incrW;
leftElement.style.setProperty('width', `${leftWidth}px`);
}
if (rightElement) {
let rightWidth = rightWidth + incrW;
rightElement.style.setProperty('width', `${rightWidth}px`);
}
};
audio.addEventListener('timeupdate', (event) => {
requestAnimationFrame(() => recalcWidth(event.detail.time));
});
И есть ли смысл использовать его для изменения стилей группы transform
?
P.S. Из документа по ссылке:
Это было прямо как если бы мне в 3 года сказали, что Деда Мороза нет)))
Строго говоря, событие raf нужно использовать всегда, когда Вы собираетесь вносить изменения в DOM. Чем Вы гарантируете себе ситуацию, когда не вызовете лишних Reflow. И при этом будучи абсолютно уверенным в том, что ваши изменения отобразятся ровно так скоро как это возможно.
tramsform насколько я помню не приводит к reflow. Но я могу и забыть. Всегда нужно контролировать себя через тот же DevTools вкладка Perfomance, записать trace. Там есть отдельный таймлайн для процессов с layout. Вот тут https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing инструкция с картинками
JavaScript: заметка о requestAnimationFrame и requestIdleCallback