Работая над одним из сайтов столкнулись с необходимостью реализовать эффект слайдов.
А именно — при вертикальном скроллинге страницы она должна перемещаться не как единое целое, а как складываемая пачка отдельных листов.
Не хотелось бы утруждать никого программным кодом (при необходимости в следующей статье), поэтому расскажу какое решение мы использовали и как к нему шли, используя вкрапления псевдокода только для уточнения некоторых моментов.
Первая мысль была использовать библиотеку для добавления parallax эффекта на страницу, коих уже достаточно много можно найти в интернете. Однако нам не нужно было мощное универсальное решение, и время затраченное на обзор, выбор и настройку стороннего решения наверняка превысило бы решение задачи в лоб своими силами. Да и жажда собрать собственные шишки и узнать основы окончательно перевесила чашу весов в пользу собственного велосипеда.
Разработку мы традиционно ведем в Firefox+firebug.
Задача по сути сводилась к изменению координат блоков сайта при скроллинге документа внутри окна браузера.
С помощью jQuery просто привязываемся к событию onscroll документа и прописываем там изменение положения блоков в зависимости от положения документа внутри окна.
Грабли №1: Если в процессе скроллинга произвести манипуляции с DOM, влияющие на высоту всего документа, то мы получим тормоза из-за перестройки и перерисовки контента, а самое неприятное, так это скачки при скроллинге из-за изменения размеров области прокрутки и реинициализации скроллбара.
Чтобы избежать этого мы приняли решение не двигать элементы находящиеся на первом уровне иерархии документа.
Каждый слайд в итоге стал представлять собой неизменный по размерам и положению на странице div (.parent), внутри которого располагается блок-обертка (.wrapper), который и содержит контент слайда.
При скроллинге документа для каждого слайда анализируется положение его .parent блока по отношению к окну браузера (значение X = jQuery(.parent).offset().top — jQuery(window).scrollTop(); ).
При отрицательном значении X делаем смещение .wrapper ( position: relative; top: X;)
Казалось бы проблема решена, однако Грабли №2 — прогон этого решения в Chrome дает неприятные ощущения. Слайды, которые должны просто задерживаться у верха окна, начинают неприятно подергиваться.
Дело в том, что в отличие от Firefox Chrome при скроллинге страницы сначала отрисовывает ее новое положение, а затем вызывает onScroll, где мы меняем координаты блока и страница отрисовывается повторно.
Исправить ситуацию позволило задание нужным элентам .wrapper фиксированного позиционирования (position: fixed;). Такие элементы не меняют своего экранного положения при скроллинге. Осталось только рассчитать смещение .wrapper относительно окна, а не родительского элемента и рывки исчезают.
Грабли №3: в некоторых мобильных браузерах событие onScroll не генерируется до полной остановки скроллинга, что приводит к чудовищным задержкам “анимации”.
Решением может стать вызов пересчета координат по таймеру, а еще лучше через requestAnimationFrame.
Полученное решение обладает одним важным достоинством, при отключении скриптов страница выглядит совершенно корректно в браузере — отключется лишь эффект слайдовости.
Автор: TemaAE