Галерея с эффектом Cover Flow на JavaScript.

Содержание:

Вступление.

Несколько лет назад, просматривая в инете галереи с эффектом «Cover Flow», наткнулся на сайт, где эффект «Cover Flow» был реализован очень красиво, в различных вариантах и возможностью переключения между ними. Скрипты были написаны на jQuery, при этом ещё минифицированными, зашифрованными и платными.
Мне захотелось сделать тоже самое, но на чистом JavaScript. Признаюсь честно, я взял с этого сайта саму идею эффекта и несколько картинок.

За прошедшее с тех пор время, плагин Simple 3D Coverflow был значительно улучшен его авторами — эффект «Cover Flow» стал более плавным, в галерее появилась адаптивность под различные разрешения и т. д.
Тем не менее, в этой статье мы рассмотрим галерею с эффектом «Cover Flow» в том виде, каким он был на момент написания мною скрипта пару лет назад.

Галерея с эффектом Cover Flow

Эффект «Cover Flow» основан на свойстве CSS3 transform, которое позволяет преобразовывать элемент в трехмерной системе координат. Если вам не приходилось сталкиваться с CSS-трансформацией, рекомендую предварительно ознакомиться с парой статей: CSS3-трансформации и CSS3 3D-трансформации.

Надеюсь всё всем понятно. Ну а теперь составим техническое задание, чтобы ничего не забыть и не пропустить.

  • 1

    Галерея будет фиксированной ширины, чтобы упростить скрипт и сконцентрироваться непосредственно на реализации эффекта Cover Flow при листании галереи.
    Если вас интересует создание адаптивной галереи, то можете изучить статью Адаптивная галерея изображений для сайта на JavaScript.

  • 2

    Для листания галереи используем следующие варианты управления:
    — кнопками навигации «prev» и «next»;
    — клавишами клавиатуры со стрелочками «←» и «→»;
    — вращением колёсика мыши;
    — клик по изображению, к которому необходимо прокрутить галерею.

  • 3

    Создадим несколько вариантов эффекта Cover Flow и обеспечим переключение между ними без перезагрузки страницы.

  • 4

    Возможно использование нескольких галерей на одной странице.

HTML-вёрстка галереи с эффектом Cover Flow.

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

HTML-вёрстка галереи очень простая и состоит из трёх основных блоков:

  1. непосредственно сама галерея;
  2. навигация по галерее с кнопками «prev» и «next»;
  3. переключение между вариантами эффекта Cover Flow.

В качестве комментария к HTML-вёрстке галереи с эффектом Cover Flow, хочу обратить внимание на пустой DIV, расположенный после каждого изображения галереи. С его помощью создаётся градиентное затенение изображения.

Таблица стилей для галереи с эффектом Cover Flow.

Конструктор для адаптивной галереи с эффектом Cover Flow.

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

При написании JS-скрипта мы будем использовать прототипное наследование. Это позволит создать несколько галерей на одной странице.
Для создания объектов галерей с эффектом Cover Flow мы будем использовать конструкторы, т. к. они хорошо подходят для создания множества похожих объектов, имеющих одинаковую структуру, с общими именами свойств и методов. В JavaScript это называется наследованием через прототипы, а объект от которого наследуются свойства и методы, называется прототипом. В нашем случае, это объект созданный конструктором. Другими словами, механизм работы наследования через прототипы заключается в наследовании и повторном использовании свойств и методов созданных в конструкторе, с возможностью расширения свойств во вновь созданном объекте.

Конструктор представляет из себя функциональное выражение (Function Expression) с набором настроек, определяющих внешний вид галереи Cover Flow, её поведение и способы управления. Эти настройки можно изменить во время инициализации галереи, заменив их значения на пользовательские.
Кроме этого, в конструкторе вызывается функция init, которая формирует разновидность эффекта Cover Flow исходя из полученных настроек.

Конструктор принимает два аргумента:

  1. id — идентификатор галерей, инициализация которой происходит в данный момент;
  2. setup — ассоциативный массив с пользовательскими настройками.

Для того, чтобы была возможность обратиться к конструктору из вне анонимной функции, запишем функцию-конструктор, как свойство объекта Window.

Теперь рассмотрим полный JS-код конструктора, дополненный комментариями:

Как видно из приведённого кода, конструктор содержит в себе настройки по умолчанию — это объект defaults. Эти настройки могут быть переназначены при вызове конструктора и их новые значения будут передаваться в аргументе setup. Позже это будет рассмотрено.
Кроме этого, в конструкторе определяются основные DOM-элементы и коллекции DOM-элементов от которых зависит каркас галереи с эффектом Cover Flow.

Вызывать функцию-конструктор будем из HTML-страницы, для чего в конце HTML-вёрстки, перед закрывающим тегом </BODY> запишем следующий JS-код:

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

Т. к. все методы наследуются от своего прототипа, то их запись будет выглядеть следующим образом:

Давайте сократим эту запись, создав переменную, которая будет ссылаться на прототип Coverflow, для этого в конец нашей анонимной функции добавим следующий JS-код:

Теперь запись функции будет выглядеть следующим образом:

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

Инициализация галереи с эффектом Cover Flow.

Инициализация галереи начинается вызовом функции init из функции-конструктора Coverflow. В качестве аргумента функция init получает тип эффекта Cover Flow и решает следующие задачи:

  1. Устанавливает настройки в зависимости от типа эффекта Cover Flow.
  2. Объединяет настройки эффекта Cover Flow с пользовательскими и дефолтными настройками, записывая результат в объект настроек options.
  3. Исходя из количества элементов в галерее, вычисляет центральный элемент и его координаты по осям X, Y и Z.
  4. Создаёт каркас галереи и размещает в нём элементы в зависимости от выбранного типа эффекта Cover Flow.
  5. Устанавливает обработчики событий для управления галереей.

JS-код функции init:

В приведённом JS-коде встретился вызов трёх новых функций — extend, creatGallery и galleryControl. Рассмотрим подробнее назначение и работу данных функций.

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

Запишем в конец анонимной самозапускающейся функции следующий JS-код:

Необходимо обратить внимание ещё на такой момент — при вызове функции extend, формируется свойство options.type, значение которого берётся из пользовательских настроек. При переключении типа эффекта Cover Flow значение этого свойства не изменится, т. к. пользовательские настройки при этом остаются неизменными, поэтому значение свойства options.type пропишем явно, используя полученный аргумент type функции init.

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

Формирование каркаса и размещение элементов галереи с эффектом Cover Flow.

В этом разделе мы рассмотрим функцию creatGallery, которая формирует каркас галереи и запускает анимацию размещения её элементов в зависимости от выбранного типа эффекта Cover Flow.
Рассмотрим алгоритм работы функции creatGallery:

  • 1

    Фиксируется время начала анимации размещения элементов галереи и регистрируется ряд переменных:
    zIndex, Z-индекс элемента галереи;
    shiftLX, смещение по оси X элементов, расположенных слева от центрального (левая ветвь элементов);
    shiftRX, смещение по оси X элементов, расположенных справа от центрального (правая ветвь элементов);
    shiftZ, смещение элементов по оси Z;
    alignment, содержание атрибута style элемента галереи.

  • 2

    Запускается функция анимации.

  • 3

    Вся галерея поворачивается по оси X на угол равный options.rotateXOut и зависящий от типа эффекта Cover Flow.

  • 4

    Позиционируется центральный элемент галереи, имеющий индекс options.currIndex. Координаты его середины совпадают с центром галереи и являются начальной точкой отсчёта для позиционирования остальных элементов галереи.

  • 5

    Устанавливаются ближайшие элементы с правой и левой стороны от центрального (текущего). У этих элементов увеличенный в 2 раза сдвиг по оси Х (options.shiftXlong) и в 3 раза по оси Z (options.shiftZlong), по сравнению с другими элементами галереи. Это обусловлено тем, что в противном случае, центральный (текущий) элемент будет закрывать собою соседние элементы.

  • 6

    Позиционируются остальные элементы левой и правой ветвей галереи.

  • 7

    После окончания анимации сохраняется в массив координата Z каждого элемента. Эта координата понадобится для анимации изменения положения элемента при наведении на него курсора.

Теперь рассмотрим JS-код, реализующий данный алгоритм.

Создадим функцию creatGallery и зарегистрируем в ней ряд переменных:

Теперь необходимо запустить функцию анимации, которая плавно расставит элементы галереи в соответствии с настройками эффекта Cover Flow.

Запомните, это очень важно.
При создании анимации на JavaScript вместо функции setInterval используйте функцию requestAnimationFrame. Эта функция позволяет синхронизировать анимацию со встроенными в браузер механизмами обновления страницы. Результатом будет более эффективное использование графического ускорителя, исключена повторная обработка одних и тех же участков страницы, меньше будет загрузка процессора и, самое главное, анимация будет более плавная, без рывков и дёрганий.

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

Зарегистрируем внутри функции creatGallery функцию анимации animate. Она представляет из себя именованное функциональное выражение. Это сделано для работы с рекурсией, т. е., чтобы позволить функции изнутри вызвать саму себя.

Первое, что делает функция animate — поворачивает всю галерею по оси X на угол, заданный в настройках.

Давайте, на примере поворота галереи по оси X, разберёмся, как работает анимация на JavaScript. На этом принципе построена вся анимация эффекта Cover Flow.

Итак, у нас есть ряд переменных:

timePassed
равна разности текущего времени и времени старта анимации. Другими словами, эта переменная содержит длительность анимации на данный момент.
duration
содержит время, отведённое на анимацию, т. е. продолжительность анимации, зависит от настроек галереи.
progress
коэффициент выполнения анимации. В процессе работы функции animate и роста значения переменной timePassed, меняет своё значение от 0 до 1.
options.rotateXOut
угол, на который должна повернуться галерея по оси X, зависит от настроек галереи.

Текущий угол поворота галереи равен произведению options.rotateXOut * progress. С ростом времени анимации timePassed, растёт коэффициент выполнения анимации progress и, как следствие, результат произведения options.rotateXOut * progress стремится к заданному углу поворота options.rotateXOut.
При каждом вызове функции animate коэффициент выполнения анимации сравнивается с 1. Если progress < 1, считаем, что анимация ещё не закончена и рекурсивно вызываем функцию анимации.

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

Теперь рассмотрим анимацию позиционирования элементов галереи при её начальном построении.

Обращаться к элементам коллекции elements для применения к ним css-трансформации, можно по их индексам в коллекции. В связи с тем, что css-трансформация у элементов левой и правой части галереи разная, необходимо определиться, какие индексы относятся к левой ветви галереи, а какие к правой.
Нам известен индекс центрального элемента — options.currIndex. Логично предположить, что элементы, у которых индекс меньше options.currIndex, относятся к левой части, а у которых больше — к правой. При этом, к элементам, у которых индекс больше или меньше на единицу индекса центрального элемента, применяется своя трансформация.

Ещё раз вкратце, т. к. это очень важно — в галерее с эффектом Cover Flow есть три группы элементов:
— центральный элемент,
— два элемента рядом с центральным,
— остальные элементы левой и правой части галереи,
к которым применяется разные значения свойств css3-трансформации.

Для получения индексов, используем цикл от 0 до options.currIndex. Используя полученные индексы, можно разделить элементы на группы и далее, применить к каждой группе свою css-трансформацию.

Галерея с эффектом Cover Flow. Позиционирование центрального элемента.

Центральный элемент располагается по центру галереи, что в принципе понятно из его названия. Соответственно, его координаты x0 и y0 совпадают с центром галереи и являются начальной точкой отсчёта для остальных элементов.

Для позиционирования центрального элемента, помещаем в переменную alignment данные для 3D-преобразования и вызываем функцию setAlignment, передавая ей в качестве аргументов индекс центрального элемента и alignment.
Устанавливаем затенение элемента, вызвав функцию setbg. Первым параметрами данной функции будет индекс элемента, у которого устанавливается затенение, а второй параметр указывает прозрачность (opacity) затенения. Т. к. центральному элементу затенение не нужно, то второй параметр будет равен 0.

Работу функций setAlignment и setbg мы рассмотрим позже.

Галерея с эффектом Cover Flow. Подготовка данных для позиционирование элементов соседних с центральным.

устанавливаем ближайшие элементы с правой и левой стороны от центрального (текущего). У этих элементов увеличенный сдвиг по оси Х (shiftXlong) и по оси Z (shiftZlong). Сдвиг этих элементов отсчитывается от центра галереи.
Напомню, увеличенный по осям X и Z сдвиг нужен для того, чтобы центральный элемент не закрывал соседние элементы.

Галерея с эффектом Cover Flow. Подготовка данных для позиционирование остальных элементов.

Для этих элементов позиционирование начинается с координат полученных для элементов, соседних с центральным: shiftLX, shiftRX и shiftZ

Галерея с эффектом Cover Flow. Применение css-трансформации к элементам галереи.

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

Мы рассмотрели отдельные части JS-кода функции creatGallery, теперь соберём их вместе:

Галерея с эффектом Cover Flow. Сохранение координаты Z элементов галереи.

Как видно из кода функции, по окончанию анимации формирования галереи, вызывается функция saveCoordinatesZ. Эта функция сохраняет координаты Z всех элементов галереи в массив arrayZ0. Данные из этого массива понадобятся при создании анимации при наведении на эти элементы.

Функция saveCoordinatesZ очень простая, отдельно рассматривать её работу я не буду, вполне достаточно будет комментариев в коде.

В своей работе функция saveCoordinatesZ вызывает функцию getStylesElements, а она в свою очередь getStylesElement. Эти функции так же очень просты и нет необходимости рассматривать каждую строчку кода. Обойдёмся комментариями, встроенными в код:

Назначение встроенных стилей элементам галереи с эффектом Cover Flow.

Рассмотрим три важные функции, упомянутые в выше приведённом JS-коде, которые, получив текущие значения сдвигов и углов поворота, прописывают CSS-код трансформации непосредственно внутри тега элемента с помощью атрибута style. Эти функции используются не только при построении, но и при листании галереи, создавая эффект Cover Flow.

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

Далее, полученный CSS-код необходимо прописать в атрибут style конкретного элемента галереи. Используем для этой цели функцию setAlignment. Аргументами этой функции является CSS-код и индекс элемента, которому его нужно применить.

Как видно на скриншоте, приведённом в начале статьи, элементы галереи имеют затенения. Причём у элементов левой ветви затенена правая часть, а у элементов правой ветви — левая. Этот эффект создаётся путём применения линейного градиента к контейнеру <DIV>, расположенному над элементом галереи.
Для реализации затенения создадим функцию setbg. Аргументами у этой функции будут: индекс текущего элемента и прозрачность.

Как видно из приведённого кода, направление градиента зависит не только от индекса элемента, но и от типа эффекта Cover Flow.

Переключение вариантов эффекта Cover Flow.

После рассмотрения анимации формирования каркаса галереи при загрузке страницы, логично разобраться, как галерея меняет свой вид при переключении типа эффекта Cover Flow.
Если при загрузке страницы, вид эффекта Cover Flow мы передаём, вызывая функцию-конструктор Coverflow, то в дальнейшем мы сможем менять разновидность эффекта при помощи созданного нами блока управления. Напомню вам его HTML-код:

Визуально блок переключения разновидностей анимации Cover Flow выглядит так:

Переключение разновидностей эффекта Cover Flow

Интерактивными элементами являются элементы списка <LI>. Клик именно по этим элементам будет вызывать переключение типа эффекта Cover Flow.

Запомните, это очень важно.
Как с точки зрения семантики, так и с точки зрения СЕО — тэг <a> должен использоваться только для формирования ссылок, ведущих на другие страницы сайта или другой интернет-ресурс. Для управления элементами текущей страницы (показать / скрыть, изменить стиль, переместить, подгрузить и т.д.) должны использоваться теги <span>, <button>, <div>, <li>. Именно они должны быть интерактивными элементами страницы.

Для упрощения и сокращения JS-кода мы не будем вешать обработчики событий на каждый элемент <LI>, а воспользуемся делегированием и с помощью функции addEventListener вешаем один обработчик на их родительский элемент <UL>. При возникновении события click на ненумерованном списке <UL>, обработчик вызовет функцию switchGalleryType.
Регистрация обработчика происходит в функции galleryControl, которую мы рассмотрим, когда будем разбираться с реализацией функционала листания галереи.

Запомните, это очень важно.
При использовании метода addEventListener теряется контекст вызова — this, который ссылается на текущий объект. Используя встроенный в JavaScript метод bind, можно напрямую передать контекст вызова в функцию обработчика события.

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

Алгоритм работы функции switchGalleryType:

  • 1

    При срабатывании события (по блоку переключения был сделан клик) и используя делегирование, определяем, что клик произошел именно по элементу <LI>, а не по пустой области его родительского элемента. Получаем значение атрибута data-type у элемента <LI>, по которому был сделан клик, значение атрибута содержит тип эффекта Cover Flow.

  • 2

    Перебираем коллекцию переключателей и удаляем у них класс active. Присваиваем класс active элементу, по которому был сделан клик.

  • 3

    Вызываем функцию init, передавая в качестве параметра тип выбранной анимации эффекта Cover Flow.

Полный JS-код функции switchGalleryType с комментариями:

Управление листанием галереи с эффектом Cover Flow.

В техническом задании мы определили четыре способа управления листанием галереи. Напомню их:
— кнопками навигации «prev» и «next»;
— клавишами клавиатуры со стрелочками «←» и «→»;
— вращением колёсика мыши;
— клик по изображению, к которому необходимо прокрутить галерею.

Всё управление галереей реализовано в функции galleryControl. В этой функции регистрируются обработчики событий, а в случае наступления этих событий, определяется направление перемещения и запускается прокручивание галереи. Кроме этого, здесь регистрируется обработчик события переключения типа анимации эффекта Cover Flow.

Галерея с эффектом Cover Flow. Управление кнопками «prev» и «next».

Давайте вспомним HTML-код блока навигация по галерее кнопками «prev» и «next»:

Мы опять воспользуемся делегированием и с помощью функции addEventListener повесим обработчик на родительский контейнер элементов <SPAN>. В атрибуте [data-show] этих элементов содержится информация о направлении листания галереи.

Запишем следующий JS-код в функцию galleryControl:

Как видите, здесь цикл while не используется, т. к. у <SPAN> нет дочерних элементов, по которым может быть сделан клик.

Галерея с эффектом Cover Flow. Управление с клавиатуры.

Обработчик события устанавливается на объект window, который представляет собой окно, содержащее DOM документ. Будет отслеживаться «клавиатурное» событие keydown, которое будет происходить при нажатии клавиши.
Нас интересует нажатие только на стрелочные клавиши «←» и «→», которые имеют код 37 и 39 соответственно. При нажатии на другие клавиши произойдёт выход из обработчика события.

Направление листания галереи зависит от кода нажатой клавиши.

Галерея с эффектом Cover Flow. Управление колёсиком мыши.

Обработчик события устанавливается на объект coverflow, т. е. галерея будет пролистываться только, если указатель мыши находится над ней. Направление листания галереи зависит от направления вращения колёсика мыши.

Галерея с эффектом Cover Flow. Скролл к элементу по которому был сделан клик.

Предыдущие способы листания галереи, при наступлении события, смещают её влево или вправо на один элемент. Сейчас мы рассмотрим прокручивание галереи к элементу, по которому был сделан клик. При этом не важно, на каком расстоянии этот элемент находится от текущего.

В данном случае я решил отойти от делегирования события к регистрации обработчика на каждом элементе. По ряду причин связанных с упрощением HTML-вёрстки, в данном случае будет трудно идентифицировать выбранный элемент и определить его позицию (индекс) в галерее. Конечно, можно изменить вёрстку, например, представив галерею в виде немаркированного списка, где элементами галереи будут элементы списка <LI>. Можно добавить им атрибуты, которые будут содержать информацию об индексе элемента и т.д. Тем не менее я решил зарегистрировать обработчики событий на каждом элементе галереи.

Итак, у нас есть коллекция элементов галереи elements, которую мы переберём с помощью метода forEach, каждому элементу назначим свой обработчик события click и получим индекс каждого элемента.

Давайте анимируем выбор элемента. Пусть элемент, при наведении, плавно выдвигается из общего ряда галереи, а если убрать курсор, так же плавно встаёт на место. Для этого назначим каждому элементу ещё по два обработчика событий — на события mouseenter и mouseleave:

Функции shifGallery, hoverShift и scroll, которые вызываются при срабатывании обработчиков событий, мы рассмотрим чуть позже, а пока — полный JS-код функции galleryControl:

Листание галереи с эффектом Cover Flow.

Эффект Cover Flow при листании галереи создаётся в функции shifGallery. Алгоритм работы этой функции и её JS-код во многом совпадают с алгоритмом и кодом функции creatGallery, поэтому отдельные участки кода я буду публиковать без объяснения, чтобы избежать ненужного повторения.

Функция shifGallery имеет два входных параметра:
1. dir — направление листания галереи;
2. duration — продолжительность анимации при смещении на один элемент.
Кроме этого, функция использует значения из объекта options.

Рассмотрим алгоритм работы функции shifGallery:

  • 1

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

  • 2

    Устанавливается запрет на листание галереи до окончания текущей анимации.

  • 3

    Фиксируется время начала анимации и регистрируется ряд переменных:
    zIndex, Z-индекс элемента галереи;
    offsetX, текущее смещение элемента по оси X;
    offsetZ, текущее смещение элемента по оси Z;
    angleY, текущий угол поворота элемента по оси Y;
    alignment, текущее значение атрибута style элемента галереи.

  • 4

    Получаем значение атрибута style каждого элемента, т. е. текущее расположение каждого элемента.

  • 5

    Запускается функция анимации.

  • 6

    Вычисляются смещение по координатам X, Z и угол поворота по оси Y в текущей итерации, а также Z-index каждого элемента.

  • 7

    На основании полученных текущих координат и угла поворота, формируется содержание (значение) атрибута style для каждого элемента галереи в текущий момент времени анимации.

  • 8

    По окончанию анимации:
    — вычисляется индекс нового текущего элемента;
    — сохраняется в массив координата Z каждого элемента;
    — снимается запрет на листание галереи.

Теперь начнём писать JS-код, реализующий рассмотренный алгоритм.
Начнём с того, что:

  1. создадим функцию shifGallery;
  2. зарегистрируем в ней ряд переменных и проведём проверку входных данных;
  3. получим значение атрибута style каждого элемента галереи;
  4. зарегистрируем внутри функции shifGallery функцию анимации animate и сделаем её вызов;
  5. укажем поведение функции после окончания времени, отведённого на анимацию сдвига.

При каждом вызове функции animate перебираются все элементы галереи и каждому элементу устанавливается значения 3D-трансформации, зависящие от текущего значения коэффициента выполнения анимации — progress.

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

Теперь подробно о составляющих этой формулы:

offsetX
Текущее значение координаты X элемента в данный момент анимации.
style.x0
Значение координаты X элемента до начала анимации, т. е. до нажатия на кнопки навигации «prev»/»next», или на клавишами клавиатуры со стрелочками «←»/»→», или вращения колёсика мыши. Значения всех координат каждого элемента были получены до начала анимации.
dir
Направление анимации. Может принимать значение 1, если галерея прокручивается в направлении «prev» и -1, если в направлении «next».
this.options.shiftX
Это значение указывает на расстояние между элементами галереи по оси X и зависит от типа эффекта Cover Flow. Значения задаются в функции init при формировании объекта настроек options. Соответственно, при сдвиге галереи на один шаг, все элементы смещаются по оси X на величину options.shiftX вправо или влево.
Напомню, что для элементов, соседних с текущим, это значение в два раза больше и хранится в свойстве options.shiftXlong.
progress
Текущий коэффициент анимации, принимающий значение от 0 (при старте анимации) до 1 (по окончанию анимации) и напрямую зависящий от времени с начала анимации. Когда progress станет равным 1, результат произведения
this.options.shiftX * progress станет равным this.options.shiftX,
т. е. элемент к концу времени анимации сместится по оси X на расстояние расстояние равное расстоянию между двумя элементами, которое заложено в настройках галереи с эффектом Cover Flow.

По такому же принципу работает анимация по остальным координатам и углу поворота.

При переборе коллекции элементов галереи, все элементы делятся на три группы. Определим условия, по которым будет происходить это деление:

— элементы правой ветви галереи;
— текущий элемент;
— элементы соседние с текущим.

К этим группам элементам применяются разные значения свойств 3D-трансформации.

У вас может возникнуть вопрос, зачем нужно делить элементы галереи Cover Flow на группы и в чём заключаются отличия в 3D-трансформации у элементов разных групп.

  1. Элементы правой части галереи развёрнуты по оси Y на угол с противоположным знаком, в отличии от элементов левой части. Кроме этого, накладываемое на них затенение, в виде линейного градиента, имеет другое направление.
  2. У текущего элемента нет угла поворота по оси Y и линейного градиента, они появляются при анимации и зависят от направления листания галереи.
    Смещение текущего элемента по оси X будет в два раза больше чем у остальных элементов галереи.
  3. В зависимости от направления листания, элемент справа или слева от текущего, должен занять его место, при этом, его угол поворота по оси Y и прозрачность затенения должны плавно уменьшиться до 0.
    Смещение этого элемента по оси X будет в два раза больше чем у остальных элементов галереи.

теперь рассмотрим, как реализованы условия, делящие элементы галереи Cover Flow на группы:

  1. Элементы правой ветви галереи.

  2. Текущий элемент.

  3. Элементы соседние с текущим.

Теперь выведем полный JS-код функции shifGallery, обеспечивающий сдвиг (пролистывание) галереи на один элемент:

Анимация поведения элемента галереи Cover Flow при наведении курсора.

Теперь рассмотрим поведение элемента, до которого мы хотим прокрутить галерею с эффектом Cover Flow, когда на него наводят курсор. Выше писалось, что при наведении курсора, элемент будет плавно выдвигаться из общего ряда элементов галереи и также плавно вставать на место, если курсор убрать.
За анимацию этого эффекта будет отвечать функция hoverShift. Вызывается эта функция при наступлении события mouseenter или mouseleave. Обработчики этих событий были зарегистрированы в функции galleryControl.

Функция hoverShift принимает три аргумента:
— элемент галереи на котором сработал обработчик события;
— индекс элемента;
— событие, на которое сработал обработчик.

В статье неоднократно рассматривалась JS-анимация, поэтому расписывать алгоритм работы функции hoverShift, достаточно подробных комментариев в коде функции.

Скролл галереи с эффектом Cover Flow до выбранного элемента.

Скролл галереи к выбранному элементу представляет из себя цикл сдвигов галереи на один элемент, т. е. последовательность вызовов функции shifGallery, где количество вызовов зависит от того, насколько элементов необходимо «проскроллить» галерею.
Отвечает за это функция scroll, вызов которой происходит при срабатывании обработчика события click, зарегистрированного в функции galleryControl.

Функция scroll очень простая, поэтому вполне будет достаточно коментариев внутри функции:

На этом создание галереи с эффектом Cover Flow закончено. Посмотреть пример галереи и скачать HTML-вёрстку и полный JS-код, Вы можете по ссылкам, указанным в начале страницы.

Комментарии

Всего: пока нет комментариев
Требования при посте комментариев:
  1. Комментарии должны содержать вопросы и дополнения по статье, ответы на вопросы других пользователей.
    Комментарии содержащие обсуждение политики, будут безжалостно удаляться.
  2. Для удобства чтения Вашего кода, не забываейте его форматировать. Вы его можете подсветить код с помощью тега <pre>:
    <pre class="lang:xhtml"> - HTML;
    <pre class="lang:css"> - CSS;
    <pre class="lang:javascript"> - JavaScript.
  3. Если что-то не понятно в статье, постарайтесь указать более конкретно, что именно не понятно.

Добавить комментарий

Ваш адрес email не будет опубликован.