Эффект слайдов на сайте. Версия вторая, дополненная и исправленная

в 7:26, , рубрики: chrome, html, javascript, parallax, веб-дизайн, велосипед, слайды, метки: , , , , ,

Некоторое время назад я публиковал статью «Эффект слайдов на сайте. Через грабли на собственном велосипеде»
Статья справедливо набрала множество замечаний, в основном касающихся отсутствия практической части и кодов.
Вашему вниманию переработанная статься снабженная живыми примерами.

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

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

Разработку мы традиционно ведем в Firefox+firebug.

Задача по сути сводилась к изменению координат блоков сайта при скроллинге документа внутри окна браузера.

С помощью jQuery просто привязываемся к событию onscroll документа и прописываем там изменение положения блоков в зависимости от положения документа внутри окна.

Грабли №1: Если в процессе скроллинга произвести манипуляции с DOM, влияющие на высоту всего документа, то мы получим тормоза из-за перестройки и перерисовки контента, а самое неприятное, так это скачки при скроллинге из-за изменения размеров области прокрутки и реинициализации скроллбара.

Чтобы избежать этого мы приняли решение не двигать элементы находящиеся на первом уровне иерархии документа.
Каждый слайд в итоге стал представлять собой неизменный по размерам и положению на странице div (.slide_wrapper), внутри которого располагается блок-обертка (.slide), который и содержит контент слайда.

Для реализации данного механизма нами был создан класс (в его javascript понимании) aldparallax.
При создании объекта в конструктор передаются параметры, определяющие набор элементов, участвующих в движении (.slide_wrapper) и массив со ссылками на функции обратного вызова.
При создании объект aldparallax привязывается к событиям scroll и resize объекта window.
При наступлении события для каждого слайда готовится массив данных (координаты текущая видимой области документа, позиция слайда в документе, координаты видимой области слайда) и вызывается коллбэк, в котором и заложен алгоритм перемещения элементов в слайде.
Внутри функции мы смещаем положение слайда внутри контейнера навстречу скроллингу (путем изменения свойства top при position: relative), что и дает требуемый эффект.

Пример 1: jsfiddle.net/88WvX/

В данном примере скрипт работает с любым количеством слайдов (достаточно внести их в html), начинает перекрытие только при достижении слайдом верха окна и в то же время корректно отрабатывает ситуации, когда слайд больше размера окна и его «залистывание» может привести к тому, что низ скроется за следующим слайдом раньше, чем появится в окне.

Казалось бы проблема решена, однако Грабли №2 — прогон этого решения в Chrome дает неприятные ощущения. Слайды, которые должны просто задерживаться у верха окна, начинают неприятно подергиваться.
Дело в том, что в отличие от Firefox Chrome при скроллинге страницы сначала отрисовывает ее новое положение, а затем вызывает onScroll, где мы меняем координаты блока и страница отрисовывается повторно.

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

Исправить ситуацию позволило задание нужным элентам .slide фиксированного позиционирования (position: fixed;). Такие элементы не меняют своего экранного положения при скроллинге.
Осталось только рассчитать смещение .wrapper относительно окна, а не родительского элемента и рывки исчезают. Корректируем нашу функцию onParallaxEvent.

Пример 2. jsfiddle.net/PWm7v/

Грабли №3: в некоторых мобильных браузерах событие onScroll не генерируется до полной остановки скроллинга, что приводит к чудовищным задержкам “анимации”.
Решением может стать вызов пересчета координат по таймеру, а еще лучше через requestAnimationFrame. Данную корректировку оставляю на самостоятельную работу читателям.

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

В следующем примере упрощенный пример одного из наших рабочих проектов.
Для предотвращения хабраэффекта код был немного упрощен и выложен на jsfiddle:

Пример 3: jsfiddle.net/2Lhvb/

Автор: TemaAE

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js