Направление скролла. Активация обратной прокрутки в Windows. Перерабатываем плагин на чистом JavaScript

Помощь 07.03.2019
Помощь

Тег предназначен для указания типа текущего документа - DTD (document type definition, описание типа документа). Необходимо, чтобы браузер понимал, как следует интерпретировать текущую веб-страницу, поскольку HTML существует в нескольких версиях, кроме того, имеется XHTML (EXtensible HyperText Markup Language, расширенный язык разметки гипертекста), похожий на HTML, но различающийся с ним по синтаксису.

Чтобы браузер знал, согласно какому стандарту отображать текущий HTML-документ необходимо в первой строке кода задавать .

Синтаксис

Пример: Обьявление

Cуществует несколько видов DOCTYPE. Есть строгие виды (strict ), которые работают на основе только определенных тегов, есть переходные (transitional ), которые допускают возможность включения дополнительных тегов, есть такие, которые работают с фреймами (frameset ).

В HTML 4.01 doctype ссылается на Document Type Definition (DTD описывает схему документа для конкретного языка разметки посредством набора объявлений), который основан на SGML . Есть 3 разных типа doctype в версии HTML 4.01.

Правила DOCTYPE HTML5 являются универсальными, включают в себя правила предыдущей версии, а также возможность работы с HTML 4 тегами и в какой-то степени с XHTML, и объединяют в себе возможности всех своих предшественников, адаптируя их для работы в новых браузерах.

HTML 4.01 Strict (HTML 4.01 Строгий)

Этот тип DTD включает все элементы и атрибуты html, за исключением визуальных (оформительских) или не рекомендованных элементов (например, font). Использование фреймов запрещено.

HTML 4.01 Transitional (HTML 4.01 Переходный)

Этот тип DTD включает все элементы и атрибуты html, включая визуальные (оформительские) и не рекомендованные элементы (например, font). Использование фреймов запрещено.

HTML 4.01 Frameset (HTML 4.01 Фрейм)

То же самое, что и HTML 4.01 Transitional, но разрешает использование фреймов.

XHTML 1.0 Strict (XHTML 1.0 Строгий)

Этот тип DTD включает все элементы и атрибуты html, за исключением визуальных (оформительских) или не рекомендованных элементов (например, font). Использование фреймов запрещено. Разметка должна быть написана, как хорошо оформленный XML.

XHTML 1.0 Transitional (XHTML 1.0 Переходный)

Этот тип DTD включает все элементы и атрибуты html, включая визуальные (оформительские) и не рекомендованные элементы (например, font). Использование фреймов запрещено. Разметка должна быть написана, как хорошо оформленный XML.

XHTML 1.0 Frameset (XHTML 1.0 Фрейм)

Аналогично XHTML 1.0 Transitional, но разрешает использование фреймов.

  • Перевод

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

Не так давно Apple представила iPhone 5S, и сайт с презентацией , где страница была поделена на секции, и каждая секция описывала одну из особенностей продукта. Я подумал, что это – замечательный способ представления продукта, исключающий возможность пропустить ключевую информацию.

Я отправился на поиски подходящего плагина, и к удивлению, не обнаружил такового. Так и родился плагин постраничной прокрутки.

Плагин постраничной прокрутки.

Плагин, основанный на jQuery, позволяющий создать раскладку для страницы с несколькими секциями при минимальном использовании разметки.

Я расскажу, как он создавался, от задумки, к планированию, тестированию и выкладыванию бесплатного кода.

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

К чему всё это?

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

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

1. Чертежи

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

Можно представлять всё в уме, а можно делать наброски.

Разобъём концепцию на мелкие задачи, решая каждую последовательно.

1. Подготовим раскладку секций
Отключим обычную прокрутку, применяя overflow: hidden к body. Расположим секции в нужной последовательности, подсчитаем и приспособим нужную информацию и классы.

2. Установим триггер ручной прокрутки
Триггер ловим через jQuery, определяем направление прокрутки, двигаем раскладку при помощи CSS.

3. Добавим возможностей
Добавим адаптивность, цикл, поддержку прокрутки на тачскринах, разбивку на страницы, и т.д.

4. Проверим в разных браузерах.
Проверим браузеры Chrome, Safari, Firefox, Internet Explorer 10 и самые популярные операционки Windows, Mac OS X, iOS and Android 4.0+.

5. Сделаем плагин доступным в репозитории
Создадим репозиторий, напишем инструкцию по использованию плагина

6. Расширим поддержку.
Изучим иные пути для увеличения поддержки плагина.

2. Строим основу

Спроектировав плагин, я занялся построением основы на этом шаблоне:

Function($) { var defaults = { sectionContainer: "section", … }; $.fn.onepage_scroll = function(options) { var settings = $.extend({}, defaults, options); … } }($)

Шаблон начинаем с модуля!function($) { … }($), который помещает глобальную переменную jQuery в локальную область – это поможет снизить нагрузку и предотвратить конфликты с другими библиотеками.

Переменная defaults содержит настройки по-умолчанию.

$.fn.onepage_scroll – основная функция, которая всё инициализирует. Если вы делаете свой плагин, не забудьте вместо onepage_scroll написать другое название.

Запретить стандартную прокрутку можно, назначив тегу body свойство overflow: hidden
через имя класса, специфичное для данного плагина. Важно использовать уникальные имена стилей, чтобы избежать конфликта с существующими. Я обычно использую аббревиатуру из названия плагина, а потом через тире – имя для стиля, к примеру: .onepage-wrapper.

Фундамент заложен, приступим к первой функции.

3. Подготовим раскладку и расположим секции

Сначала я пошёл неправильным путём. Я думал, что расположу все секции по порядку, проходя их в цикле. Что у меня получилось сначала:

Var sections = $(settings.sectionContainer); var topPos = 0; $.each(sections, function(i) { $(this).css({ position: "absolute", top: topPos + "%" }).addClass("ops-section").attr("data-index", i+1); topPos = topPos + 100; });

Цикл перебирает все селекторы (sectionContainer определён в разделе переменных по-умолчанию), назначает position: absolute и присваивает каждому следующему разделу правильную top позицию, чтобы они не наезжали друг на друга.

Положение сверху (top) хранится в topPos. Начинаем с нуля и с каждым циклом прибавляем. Чтобы каждая секция занимала всю страницу, я устанавливаю их высоту в 100% и прибавляю к topPos 100.

Разработка и проверка заняла у меня пару часов, но на следующем шаге я понял, что всё это было не нужно.

4. Ручной триггер и преобразование страницы

Можно было бы подумать, что следующий шаг – передвигаем каждую секцию в новое положение, когда срабатывает триггер прокрутки… Но есть способ лучше. Вместо сдвига каждой из секций в цикле, я просто помещаю их все в один контейнер и использую функцию translate3d из CSS3 для его сдвига. Эта функция поддерживает проценты, мы можем передвигать секции так, чтобы они точно позиционировались в окне, не пересчитывая всё заново. Кроме того, это облегчает контроль над скоростью и другими параметрами анимации.


Первое решение – не всегда самое эффективное, поэтому не забывайте оставлять время на эксперименты.

Теперь остаётся только определить направление прокрутки и сдвигать контейнер в нужную сторону.

Function init_scroll(event, delta) { var deltaOfInterest = delta, timeNow = new Date().getTime(), quietPeriod = 500; // Cancel scroll if currently animating or within quiet period if(timeNow - lastAnimation < quietPeriod + settings.animationTime) { event.preventDefault(); return; } if (deltaOfInterest < 0) { el.moveDown() } else { el.moveUp() } lastAnimation = timeNow; } $(document).bind("mousewheel DOMMouseScroll", function(event) { event.preventDefault(); var delta = event.originalEvent.wheelDelta || -event.originalEvent.detail; init_scroll(event, delta); });

Сначала цепляем функцию на событие mousewheel (DOMMouseScroll в Firefox), тогда можно будет перехватить данные и определить направление. Встраиваем в обработку init_scroll, которая получает wheelData для этого.

В идеальном мире достаточно было бы посчитать изменение wheelData. Однако при анимации последовательностей необходимо встроить проверку, чтобы событие-триггер не дублировалось (иначе при анимации изображение будет перекрываться). Можно использовать setInterval для вызова каждой анимации по очереди, но это не обеспечит точности и надёжности, т.к. каждый браузер обрабатывает его по-своему. К примеру, у Chrome и Firefox setInterval тормозит в неактивных вкладках, в результате функции не отрабатывают вовремя. В результате я остановился на использовании функции, возвращающей текущее время.

Var timeNow = new Date().getTime(), quietPeriod = 500; … if(timeNow - lastAnimation < quietPeriod + settings.animationTime) { event.preventDefault(); return; } … lastAnimation = timeNow;

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

If (deltaOfInterest < 0) { el.moveDown() } else { el.moveUp() }

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

$.fn.transformPage = function(settings, pos, index) { … $(this).css({ "-webkit-transform": (settings.direction == "horizontal") ? "translate3d(" + pos + "%, 0, 0)" : "translate3d(0, " + pos + "%, 0)", "-webkit-transition": "all " + settings.animationTime + "ms " + settings.easing, "-moz-transform": (settings.direction == "horizontal") ? "translate3d(" + pos + "%, 0, 0)" : "translate3d(0, " + pos + "%, 0)", "-moz-transition": "all " + settings.animationTime + "ms " + settings.easing, "-ms-transform": (settings.direction == "horizontal") ? "translate3d(" + pos + "%, 0, 0)" : "translate3d(0, " + pos + "%, 0)", "-ms-transition": "all " + settings.animationTime + "ms " + settings.easing, "transform": (settings.direction == "horizontal") ? "translate3d(" + pos + "%, 0, 0)" : "translate3d(0, " + pos + "%, 0)", "transition": "all " + settings.animationTime + "ms " + settings.easing }); … }

Это метод трансформации, который сдвигает секции. Я делал их на яваскрипте вместо задания отдельных стилей, чтобы у разработчиков была возможность изменять настройки в самом плагине (в основном, скорость и ускорение анимации), и не надо было рыться в файле со стилями в поисках настроек. Кроме того, процент трансформации всё равно нужно пересчитывать, поэтому без яваскрипта не обойтись.

5. Дополнительные возможности

Сначала я не хотел ничего добавлять, но получил столько отзывов от сообщества GitHub, что решил постепенно улучшать плагин. Я выпустил версию 1.2.1, в которой добавляется множество обратных вызовов и циклов, и что самое сложное – адаптивность.

Я не делал плагин изначально с расчётом на мобильные платформы (о чём сожалею). Вместо этого пришлось отслеживать и пересчитывать события тачскрина в подходящий для использования в init_scroll вид. Не во всех браузерах это работает хорошо, поэтому пришлось встроить возможность отката – когда браузеру возвращается нормальная прокрутка при достижении определённой ширины окна.

Var defaults = { responsiveFallback: false … }; function responsive() { if ($(window).width() < settings.responsiveFallback) { $("body").addClass("disabled-onepage-scroll"); $(document).unbind("mousewheel DOMMouseScroll"); el.swipeEvents().unbind("swipeDown swipeUp"); } else { if($("body").hasClass("disabled-onepage-scroll")) { $("body").removeClass("disabled-onepage-scroll"); $("html, body, .wrapper").animate({ scrollTop: 0 }, "fast"); } el.swipeEvents().bind("swipeDown", function(event) { if (!$("body").hasClass("disabled-onepage-scroll")) event.preventDefault(); el.moveUp(); }).bind("swipeUp", function(event){ if (!$("body").hasClass("disabled-onepage-scroll")) event.preventDefault(); el.moveDown(); }); $(document).bind("mousewheel DOMMouseScroll", function(event) { event.preventDefault(); var delta = event.originalEvent.wheelDelta || -event.originalEvent.detail; init_scroll(event, delta); }); } }

Определим переменную по-умолчанию. Используем responsiveFallback, чтобы определить, когда плагин должен делать откат. Этот код определяет ширину браузера. Если ширина меньше значения из responsiveFallback, функция снимает все события, переносит страницу на начало и позволяет прокручивать её как обычно. Если ширина превосходит значение, плагин проверяет наличие класса disabled-onepage-scroll, чтобы узнать, инициализирован ли он. Если нет – инициализируется заново.

Решение не идеально, но даёт возможность разработчикам и дизайнерам выбирать, как показывать их сайт на мобильной платформе, вместо того чтобы полностью отвергать эти платформы.

6. Тестирование в разных браузерах.

Тестирование – важная часть разработки, перед выпуском плагина надо убедиться, что он работает на большинстве машин. Я всегда разрабатываю в Chrome – во-первых, мне нравятся его инструменты разработчика, во-вторых я знаю, что если плагин работает в Chrome, скорее всего он будет работать в Safari и Opera.

Обычно я использую Macbook Air для разработки, а дома у меня есть PC для проверки. После того, как плагин работает в Chrome, я проверяю его вручную в Safari, Opera, и в конце – в Firefox на Mac OS X, а затем - Chrome, Firefox и Internet Explorer 10 на Windows.

Это не все возможные браузеры, но опенсорс хорош тем, что другие разработчики смогут сами протестировать и поправить ошибки – в этом и состоит его смысл. Можно не делать сразу идеальный продукт, а задать трамплин для старта.

Не забудьте тестировать свои плагины на мобильных устройствах.

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

7. Выкладываем плагин в опенсорс

Последний шаг – делимся плагином на GitHub. Для этого нужно создать там аккаунт, настроить Git и создать новый репозиторий. Затем клонировать его на локальную машину – это создаст директорию с названием плагина. Копируем туда плагин и настраиваем структуру.

Структура репозитория

Настраиваете, как вам удобно. Я делаю так:

Директория demo содержит работающие демки, со всеми необходимыми ресурсами
- обычная и сжатая версия плагина лежат в корне
- CSS и тестовые ресурсы, типа картинок (при необходимости) лежат в корне
- файл readme в корне

Структура readme

Важный этап – написание понятных инструкций для опенсорс-сообщества. Обычно я пишу их в readme, но для сложных случаев может понадобиться wiki-страница. Как я пишу readme:

1. Введение
Объясняю назначение плагина, даю изображение и ссылку на демку.
2. Требования и совместимость.
Лучше вынести эту секцию повыше, чтобы сразу было ясно, сможет ли человек воспользоваться плагином.
3. Основные принципы использования
Пошаговые инструкции, начиная от подключения jQuery, заканчивая HTML-разметкой и вызовом функции. Также описываются настройки.
4. Продвинутое использование.
Более сложные инструкции – публичные методы, обратные вызовы и другая полезная информация.
5. Другие ресурсы
Ссылки на обучалку, спасибки и т.п.

8 Расширяем поддержку

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

Но для очистки совести я переработал плагин на чистом яваскрипте (также доступна версия с поддержкой Zepto). На чистом JS нет необходимости включать jQuery, всё работает «из коробки».

To make amends, and exclusively for Smashing Magazine’s readers, I have rebuilt One Page Scroll using pure JavaScript (a Zepto version is also available). With the pure JavaScript version, you no longer need to include jQuery. The plugin works right out of the box.

Чистый JS и версия для Zepto

Перерабатываем плагин на чистом JavaScript

Такая переработка может показаться тяжким делом, но это только спервоначалу. Самое сложное – не ошибиться с математикой. Т.к. я это уже сделал, разработка вспомогательных функций для избавления от jQuery заняла у меня лишь несколько часов.

Плагин основывается на CSS3, поэтому нужно было просто заменить вызовы jQuery на аналогичные собственные. Заодно я реорганизовал структуру скрипта:

Значения переменных по-умолчанию
Всё то же, что и в предыдущей версии
- функция инициализации
Подготавливает и располагает раскладку и инициализацию того, что происходит, когда вызывается функция onePageScroll. Здесь сидят все процедуры, назначающие имена классов, атрибуты и стили позиционирования.
- приватные методы
Все внутренние методы плагина – события прокрутки, трансформация страницы, адаптивный откат и отслеживание прокрутки.
- публичные методы
Все методы для разработчиков: moveDown(), moveUp() и moveTo()
- вспомогательные методы
Всё, что переопределяет вызовы jQuery.

Встретилась пара неприятных моментов – отдельная функция только для того, чтобы добавить или убрать имя стиля, или использование document.querySelector вместо $. Но в конце мы получили лучше структурированный плагин.

Перестраиваем плагин для Zepto

Я решил поддержать Zepto, несмотря на то, что он рассчитан только на самые современные браузеры (IE10+), т.к. он работает быстрее и эффективнее чем jQuery 2.0+, при этом имеет более гибкое API. Zpeto в 4 раза меньше jQuery, что сказывается на скорости загрузки страницы. Из-за того, что люди чаще используют смартфоны, Zepto становится лучшей альтернативой.

Переделывать плагин с jQuery на Zepto проще, потому что у них сходные API. Почти всё одинаково, кроме части с анимацией. Поскольку у функции Zepto $.fn.animate() есть поддержка CSS3-анимации и поддержка обратного вызова animationEnd, следующую часть:

$(this).css({ "-webkit-transform": "translate3d(0, " + pos + "%, 0)", "-webkit-transition": "-webkit-transform " + settings.animationTime + "ms " + settings.easing, "-moz-transform": "translate3d(0, " + pos + "%, 0)", "-moz-transition": "-moz-transform " + settings.animationTime + "ms " + settings.easing, "-ms-transform": "translate3d(0, " + pos + "%, 0)", "-ms-transition": "-ms-transform " + settings.animationTime + "ms " + settings.easing, "transform": "translate3d(0, " + pos + "%, 0)", "transition": "transform " + settings.animationTime + "ms " + settings.easing }); $(this).one("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend", function(e) { if (typeof settings.afterMove == "function") settings.afterMove(index, next_el); });

Можно заменить таким кодом:

$(this).animate({ translate3d: "0, " + pos + "%, 0" }, settings.animationTime, settings.easing, function() { if (typeof settings.afterMove == "function") settings.afterMove(index, next_el); }); }

Zepto позволяет делать анимацию без определения всех стилей или самостоятельного назначения обратных вызовов.

И зачем этим заморачиваться?

Поскольку всё больше людей используют jQuery, он становится всё более сложным и иногда тормозит. Если сделать поддержку других фреймворков, ваш плагин будет более популярным.
Переделка с самого начала также поможет вам в будущем делать плагины лучше. jQuery и другие библиотеки прощают мелкие ошибки, типа пропущенных запятых – в результате вы не очень заботитесь о качестве своей работы. Без этих поблажек на чистом JavaScript я лучше чувствовал работу своего плагина – что как работает, что влияет на производительность, и что можно улучшить.

Хотя библиотеки типа jQuery облегчили нам жизнь, их использование – не самый эффективный метод достижения цели. Некоторые плагины могут обойтись и так.

Заключение.

Ну вот вам и весь процесс создания плагина «One Page Scroll». Были ошибки, но я учился на них по ходу разработки. Если б я разрабатывал его сегодня, я бы сконцентрировался на мобильных устройствах, и добавил бы больше комментариев в код.

Без поддержки таких сообществ, как GitHub, StackOverflow и Smashing Magazine я бы не смог сделать плагин так быстро. Эти сообщества сильно помогали мне в работе, поэтому я и делаю свои плагины доступными бесплатно для всех желающих. Этой мой способ расплатиться за замечательную поддержку.

Каким боком сегодняшняя хитрость относится к нашему сайту? На первый взгляд, никаким. Но если на вашем Маке в разделе Boot Camp живёт Windows, то вы уже наверняка заметили, что в Microsoft менять направление скроллинга мыши и трекпада не планировали и не собираются. Из-за этого получается, что в Mac OS X контент в окнах будет следовать за движением пальца (т.е. reverse scrolling), а в Windows вы будете двигать ползунок на экране, а сам контент будет ехать в другую сторону.

В общем, если перестроиться с одного подхода к управлению мышью на другой у вас не получается, пора переходить к решительным действиям. Есть два пути (вариант с удалением Windows и её переносом в виртуальную машину рассматривать не будем):

  • отключить обратный скроллинг в Lion или Mountain Lion . Это делается в настройках системы, в пультах «Мышь» и «Трекпад» соответственно
  • включить обратный скроллинг в Windows . Как ни странно, там для этого предусмотрен параметр в системном реесте, правда, найти его — отдельное приключение

Поскольку лёгких путей мы не ищем, сегодня мы расскажем о второй альтернативе — активации обратного скроллинга в Windows.

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

В списке устройств выберите вашу мышь двойным кликом. Перейдите на вкладку «Сведения», в выпадающем списке вам нужен будет пункт «ИД оборудования»:

Обратите внимание на первую строку, начиная с букв VID (например, VID_203A&PID_FFFC&REV_0100&MI_01). Запомните эту комбинацию.

На клавиатуре нажмите Command+R, в открывашемся окошке введите regedit и нажмите Enter. Откроется редактор реестра Windows. Слева выберите ветку HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\HID . Вы увидите список мышей и трекпадов, обозначенных комбинациями VID, PID и MI. Вам нужно будет опознать здесь настраиваемое устройство:

Внутри устройства вы можете обнаружить ещё несколько папок. В каждой из них нужно зайти внутрь папки Device Parameters и изменить значение параметра FlipFlopWheel с 0 на 1. После перезагрузки в Windows заработает обратный скроллинг.

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

Function addEvent(elem, type, handler){ if(elem.addEventListener){ elem.addEventListener(type, handler, false); } else { elem.attachEvent("on"+type, handler); } return false; } function scrollDirection(){ var weelEvt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel", el = document.body; addEvent(el, weelEvt, function(e){ var evt = e.originalEvent ? e.originalEvent: e, delta = evt.detail ? evt.detail*(-40) : evt.wheelDelta console.log("Скроллим " + (delta > 0 ? "вверх" : "вниз")); }); } // Вешаем обработчик события загрузки документа - DOM-Ready addEvent(window, "load", scrollDirection); // Для jQuery - просто вызываем функцию после загрузки DOM /*$(function(){ scrollDirection(); });*/

Что-то особо расписывать, я смысла не вижу. Единственное, что можно просто для себя отметить, так это то, что в данном случае "отличился" FireFox, со своим нестандартным событием "DOMMouseScroll".
Для лучшего понимания и восприятия, я решил сделать один примерчик, где предположим следующую задачу: при каждом скролле пользователя, он должен четко попадать на следующий/предыдущий раздел страницы, не проскакивая его, даже если скроллил интенсивно. При этом, будем подгружать в текущий блок соответствующий контент. Соорудим такой HTML и CSS:

* { margin: 0; padding: 0; } #grid li { list-style: none; height: 300px; border-bottom: 1px dotted #333; } #fake {height: 5000px;} /* только для того, чтоб точно был скроллбар */

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

$(function(){ var flag = false, // нужен для того, чтоб предотвращать действия во время анимации bn = 0, // индекс текущего блока blocks = $("#grid li"), // все блоки cnt = blocks.length, // кол-во блоков mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel"; // событие прокрутки колеса blocks.eq(0).load("loadblocks.html #b0"); // сразу подгружаем контент в первый блок // функция определения направления прокрутки колеса function getDelta(e){ var evt = e || window.event; evt = evt.originalEvent ? evt.originalEvent: evt; return delta = evt.detail ? evt.detail*(-40) : evt.wheelDelta; } // ловим событие прокрутки $(document).on(mousewheelevt+".my_wheel", function(e){ e.preventDefault(); // отменяем обычное поведение (страница не скроллится) if(flag) return false; // если flag == true, значит в данный момент происходит анимация if(getDelta(e) > 0){ if(bn <= 0) return false; // если дошли до первого блока, то отменяем дальнейшие действия --bn; // если блок не первый, то высчитываем индекс предыдущего блока } else { if(bn >= cnt-1) return false; // если дошли до последнего блока, то отменяем дальнейшие действия ++bn; // если блок не последний, то высчитываем индекс следующего блока } flag = true; // ставим флаг, указывая, что анимация началась $("html, body").finish().animate({ scrollTop: blocks.eq(bn).offset().top // прокручиваем страницу до вычисленного по индексу блока }, 1000, function(){ blocks.eq(bn).load("loadblocks.html #b" + bn); // подгружаем контент для блока flag = false; // снимаем флаг, указывая, что анимация завершена }); }); });

Расписал всё в комментариях, но осталось объяснить то, откуда подгружаются данные. В методе load() , есть возможность не только указать документ, который нужно загрузить, но и определить какой именно элемент нам будет нужен. В примере, я использовал обычный html-документ, в котором несколько элементов (по числу наших блоков ) имеют ID от "b0" до "b6". Получив индекс текущего блока, мы подгружаем элемент с соответствующим id.

Пробуйте, экспериментируйте, а главное помните о том, что некоторые вещи, которые сегодня вам могут и не понадобиться - завтра могут очень сильно выручить. А если возникнут какие-то неординарные вопросы или задачи, то пишите их в этой теме или в разделе "



Рекомендуем почитать

Наверх