- PVSM.RU - https://www.pvsm.ru -

Высокопроизводительный JavaScript-параллакс

Здравствуйте!

Я — Фёдор furikuretsu Ананьев, веб-разработчик студии Hot Dot, и сегодня я дам несколько простых советов для тех, кто хочет сделать своё JS-параллакс-приложение очень и очень быстрым.

Рассказ будет основываться на опыте, полученном из создания главной страницы нашего нового сайта hotdot.pro [1]. Эта страница разделена на несколько слайдов, при этом каждый из слайдов принимает размер окна браузера. В каждом слайде могут быть или не быть плавающие параллакс-слои. Фон страницы тоже движется по законам параллакс-слоя.

Всё начинается с JS

Первая, очевидная проблема, которую хочется решать — скрипты.

— Почему нам захочется её решать?

Скрипты отвечают за то, чтобы изменять положение слоя в нашей модели параллакса и вносить изменения в DOM. Слоев в более-менее внушительном приложении есть много. И чем логически ближе код перед вашими глазами находится к коду отрисовки одного слоя, тем больше раз на секунду он будет вызван браузером и тем больше вам будет хотеться увеличить его скорость.

Пример:
Если в нашем параллаксе есть пять слайдов, в каждом из слайдов — в среднем по три слоя, а обновляем параллакс мы с минимально допустимой кино-частотой в 25 FPS, то ваш код, ответственный за отрисовку одного слоя, будет вызван

5 × 3 × 25 = 375 раз в секунду.

Такая математика мотивирует держать на счету каждую операцию в часто используемых местах кода.

2D-модель плавающего слоя в контейнере давно опробована, не представляет сложности для старшеклассника и в этой статье будет опущена. Что стоит отметить, однако, так это то, что для слоя применимо эмпирическое правило:

Для обновления позиции слоя достаточно двух операций:

  • умножения некоторого неизменного коэффициента, присущего данному слою, на его смещение внутри родителя
  • прибавления результата первой операции к некоторому неизменному начальному положению, присущему данному слою.

— Почему это правило важно для нас?

Потому что благодаря нему нам не нужно конструировать позицию слоя X при каждом изменении положения зрителя из ширины слоя Х, положения слоя Х в родителе, положения зрителя и ширины родителя. Вместо пяти и более операций нам достаточно сделать всего две, указанные выше. Нужно лишь выделить специфичные для слоя X коэффициент и начальное смещение при инициализации слоя.

Для вашего душевного состояния применимо еще одно эмпирическое правило:

Когда вы производите по две операции вместо пяти+ по 375 раз в секунду,
вы чувствуете себя гораздо лучше.

Браузер рисует быстрее вашего знакомого фрилансера, но все же недостаточно быстро

Если мы являемся оптимизаторами, которые пришли в мир разработки под браузеры не очень давно, то открытием для нас станет то, что рисование элементов, находящихся пусть даже за пределами экрана, все равно происходит.

Мы, привыкшие к классическим приемам в 3D-движках, можем думать, что все за пределами экрана будет как-то оптимизированно убрано из очереди на отрисовку. Но оно не будет убрано.

Следствие:
Если у вас есть возможность скрывать (то есть накладывать css-правила display:none) в момент Х те элементы, которые не появляются на экране в момент Х — пожалуйста, всеми возможными путями делайте это.

В случае параллакса элементы есть слайды, и на нашу удачу определение свойства «находится за пределами экрана» довольно тривиально.

Видеокарта

  • В webkit- и gecko-браузерах вы получаете мгновенный прирост производительности, если организуете перемещение абсолютно расположенных слоев с помощью translate3d вместо left.
  • В Opera доступна только двухмерная версия — translate. В моём случае выигрыш производительности от её применения был сомнителен.
  • Internet Explorer отлично делает все остальные браузеры при использовании классического left для смещения слоев. Довольно занятно то, что в моём случае применение translate3d снижало его производительность.

Нам также хорошо понятно, что при переходе на translate мы потеряем возможность задавать координаты или смещение в процентах. Будем держать в голове, что в некоторых случаях это ограничение довольно болезненно.

Инвалидация

Очень ценно знание того, что совсем небольшое изменение DOM — в том числе и узлов, находящихся ближе к листьям, чем к корню — вызывает очень дорогую перерисовку всего и вся на экране.

— Что это значит для меня на практике?

Если в процессе скольжения пользователя по нашей странице мы оставляем проигрываться какую-нибудь безобидную маленькую анимацию в далеком и даже скрытом от нас слайде, браузер запустит процесс перестройки нашей страницы и последующую перерисовку. Запустит каждый раз, когда анимация будет делать шаг. И это в то время, когда пользователь прокручивает страницу, а процессор и так старается изо всех сил двигать слои в больших количествах быстро. Частота шага, например, в JQuery — 13 миллисекунд. Brace yourselves [2]: будет больно.

— Можно ли менять хоть что-то, пока пользователь скользит по странице?

Да. Вы можете без больших затрат менять позиции элементов, ведь такие изменения вызовут не перерисовку, а только перекомпозицию элементов. Перекомпозиция происходит весьма быстро, не требует перерисовки слоев и может производиться целиком на видеокарте, что определенно представляет для нас выгоду.

Перемещением слоев, однако, наши возможности по модификации DOM заканчиваются, если мы следим за производительностью.

Красивое решение:
Отключить все анимации пока пользователь передвигается по странице. Так очень дорогие для процессора анимации будут проигрываться только тогда, когда пользователь никуда не двигается, и параллакс пребывает в статике. Когда же пользователь движется, процессор сосредоточит силы только на перемещении слоев параллакса.

Статистика

Взглянем на статистику Хрома для двух версий страницы нашей студии: с отключенными и включенными оптимизациями. Давайте будем великодушными и не будем отключать у первой версии оптимизированный JS, а еще оставим ей совсем небольшие оптимизации рисования.

Высокопроизводительный JavaScript параллакс

Высокопроизводительный JavaScript параллакс

Тест был краток. Я проехал сайт слева направо, не очень торопясь. Но поэтому тест был также и очень жесток со второй версией, ведь ей надо постоянно скрывать и показывать, скрывать и показывать слайды!

Что мы видим сначала? Весь первый график залит зеленым. Очень, очень много рисования и перерисовывания каждый кадр. Огромная работа для браузера, проделанная на центральном процессоре, и очень неприятные ощущения для пользователя.

На втором графике зелени в разы меньше. Куда больше пустых серых прямоугольников. Которые есть и на первом графике, но совсем не такой высоты. Что они значат? То, что во втором случае на очень и очень многих кадрах браузер справляется со своей работой так быстро, что может заниматься чем-то другим большую часть времени, отведенного на кадр. В первом случае браузер едва успевает перевести дух.

Редкие случаи высоких цветных столбцов на втором графике, когда браузер тратит много времени на работу, обусловлены необходимостью переключать видимость слайдов и являются ценой, которую мы платим за потрясающую производительность в моменты скольжения туда-обратно между двумя слайдами.

Взглянем и на колоссальную разницу во фрэймрэйте: если на первом графике браузер редко выдает больше, чем тридцать кадров в секунду, то на втором графике он редко выдает меньше, чем тридцать кадров в секунду.


Это отличный результат.
Техники, которые мы с вами рассмотрели, требовали большого труда и раздумий.
Но они же буквально вырвали нас из болота тормозов в царство производительных web-приложений.

Я надеюсь, что мой труд окажется полезным для вас в ваших проектах, и благодарю вас за внимание к труду нашей студии.
Удачи!

Автор: codingdream

Источник [3]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/31137

Ссылки в тексте:

[1] hotdot.pro: http://hotdot.pro

[2] Brace yourselves: http://www.google.com/url?q=http%3A%2F%2Fknowyourmeme.com%2Fmemes%2Fimminent-ned-brace-yourselves-x-is-coming&sa=D&sntz=1&usg=AFQjCNGQej4o1ekwHK04qdb6aQbwADdqiA

[3] Источник: http://habrahabr.ru/post/175341/