Фотогалерея товаров для интернет-магазина.

Вступление.

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

Для начала, давайте определимся со структурой фотогалереи и способами управления ею.

Итак, структура галереи для интернет-магазина будет состоять из трёх основных блоков:
1. блок с тумбами картинок;
2. блок, куда будет выводится полноразмерная картинка;
3. блок с кнопками навигации по галереи.

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

Вроде со всем определились, ничего не упустили. Давайте приступим непосредственно к созданию фотогалереи.

HTML-вёрстка галереи для интернет-магазина.

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

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

Тумбы и большие фото разнесены по разным папкам — thumbnail и photos соответственно. Их можно было бы положить и в одну папку, добавив именам картинок префиксы, чтобы различать, где тумба, а где полноразмерное фото. При этом сам js-скрипт не изменится.
Как видите из вёрстки, я не стал оборачивать ни тумбы, ни кнопки навигации в дополнительные <div> или <li> — в этом нет совершенно никакой необходимости и незачем усложнять вёрстку и замусоривать её лишними элементами.

Ещё один немаловажный момент. В блоке <div class="photo-box"></div> по умолчанию находится фотография. Это необходимо для того, чтобы пока не загрузился скрипт, в галерее не было пустого места.

Запомните, это очень важно.
Не нужно оборачивать тумбу ссылкой, используя её href, как указатель на полноразмерную фотографию. Как с точки зрения семантики, так и с точки зрения СЕО — тэг <a> должен использоваться только для формирования ссылок, ведущих на другие страницы сайта или другой интернет-ресурс.
JS-скрипту, для вывода полноразмерного фото, достаточно src тумбы.

Таблица стилей галереи для интернет-магазина.

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

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

Пишем JS-скрипт фотогалереи для интернет-магазина.

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

При написании JS-скрипта мы будем использовать конструкцию Class. Это позволит создать несколько экземпляров галереи товаров для интернет-магазина на одной странице.

Создание экземпляров фотогалерей товаров для интернет-магазина.

В-первую очередь, создадим коллекцию фотогалерей, которые расположены на странице. Далее, с помощью метода for...of переберём полученную коллекцию, при этом мы выполним следующие действия:
— создадим экземпляр текущей галереи, используя конструктор класса Gallery;
— зарегистрируем обработчики событий.

Весь дальнейший JS-код мы будем писать внутри конструкции class Gallery { ... }.

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

Конструктор, кроме инициализации объектов и переменных, вызывает функцию registerEventsHandler(), которая регистрирует обработчики событий на странице:

Вывод полноразмерной фотографии в галерее для интернет-магазина.

Теперь рассмотрим функцию вывода полноразмерной фотографии — showPhoto(). Аргументом этой функции является индекс или текущей тумбы, или рассчитанный функциями управления выводом полноразмерного фото.
Итак, на вход функции showPhoto поступил индекс. Считываем у тумбы с таким индексом значение атрибута src и заменяем в нём название папки, в которой хранятся фотографии с thumbnails на photos. В результате такой нехитрой операции получаем путь (src) к большой фотографии. Полученное значение присваиваем атрибуту src объекта image, в результате чего, на экран выводится фото в полный размер.

Код функции showPhoto() и комментарии к нему:

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

Замените в ней thumbnails и photos на префикс_тумбы и префикс_фото соответственно. Больше ничего исправлять не нужно.

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

Расширенное управление фотогалереей для интернет-магазина.

Прежде чем начинать разбираться с функциями управления галереей, нужно вспомнить основы JavaScript, а именно, взятие остатка %. Результат a % b – это остаток от деления a на b. На этом основано получение индекса очередной фотографии, который является аргументом функции showPhoto.

Листаем галерею с помощью кнопок навигации.

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

Код функции buttonControl() и комментарии к нему:

Листание галереи кликом по полноразмерной фотографии.

Вешаем на объект image обработчик события. Передаём функции showPhoto индекс очередного фото, равный остатку от деления увеличенного на единицу текущего индекса на количество фотографий в галерее.

При срабатывании обработчика события вызывается функция imageControl().

Теперь можно кликать по полноразмерному фото, листая галерею по кругу.

Листаем галерею стрелками «влево» и «вправо» на клавиатуре.

С помощью функции addEventListener вешаем на страницу с фотогалереей обработчик события keydown — нажатие на любую клавишу клавиатуры. При срабатывании обработчика события keydown, вызывается функция keyControl().
Поучаем код нажатой клавиши. Если этот код равен 37 (влево) или 39 (вправо), вызываем функцию showPhoto с соответствующим аргументом. В противном случае, прекращаем работу функции.

Код функции keyControl() и комментарии к нему:

Листаем галерею вращая колёсико мышки.

Управление выводом фото колёсиком мышки будет срабатывать только в том случае, если было наведение курсора на полноразмерную фотографию. Для этого обработчик события повесим на объект image.

Если наступило событие wheel — прокручивание колёсика мышки, вызывается функция wheelControl().
По значению свойства deltaY события wheel определяем направление вращения колёсика. Далее, вызываем функцию showPhoto с аргументом, зависящим от направления вращения.

Код функции wheelControl() и комментарии к нему:

Листаем галерею кликом по «тумбе» — маленькой фотографии.

Учитывая, что малоразмерных фотографий может быть очень много, снова используем делегирование событий. Повесим обработчик события на родительский элемент — объект thumbsBox и при срабатывании обработчика вызовем функцию thumbControl().

В функции thumbControl(), в-первую очередь, определяем картинку, по которой был сделан клик. Далее, нам необходимо определить индекс картинки в коллекции thumbs, чтобы передать этот индекс в функцию showPhoto() для вывода полноразмерного фото. И вот здесь у нас возникает проблема.
Индекс можно определить с помощью встроенного метода indexOf, но этот метод есть только у массива, у коллекции он отсутствует. Есть два варианта решения этой проблемы:
1. Преобразовать коллекцию thumbs в массив и далее спокойно использовать метод indexOf.
2. Заимствование (одалживание) метода. Мы берём (заимствуем) метод indexOf из обычного массива [].indexOf. И используем [].indexOf.call, чтобы выполнить его в контексте thumbs.

Посмотрим JS-код первого и второго вариантов:

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

Полный код функции thumbControl() и комментарии к нему:

Заключение.

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

Комментарии

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

    • Вальдемар Рома Ответить 5 июля 2018 в 23:04

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

  • Можете мне тоже помочь? не работает с двумя галереями..

    • Вальдемар Яромир Ответить 5 января 2020 в 19:38

      Проверьте уникальность id у каждой галереи и их соответствие при вызове конструктора.

  • Не как не получается сделать две разные галереи на одной странице.

    • Вальдемар Роман Ответить 19 марта 2020 в 15:38

      Обновил архив. Оказывается в нём не доставало файлов. Смотрите HTML и JS с расширением prototype.
      Приношу извинения, за неполный архив.

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

    • Вальдемар Андрей Ответить 8 мая 2020 в 17:18

      Так трудно, что-либо посоветовать не видя вашей сборки. Посмотрите в консоли, есть ли какие-то ошибки скрипта js.

  • Здравствуйте. Спасибо за галерею, нужная вещь. Подскажите как добавить такой стиль, присвоение класса выбранной тумбе для выделения ее своим стилем?

    • Вальдемар Сергей Ответить 13 июня 2023 в 10:08

      В ф-ии showPhoto() вычисляется текущая тумба this.thumbs[i]. Нужно перебрать с помощью for…of коллекцию тумб this.thumbs и сравнить каждый элемент коллекции с this.thumbs[i]. Если они совпадают, то добавить элементу коллекции класс ‘active’, если нет — убрать.

      Совет. Не делайте рамку для выделения непосредственно самой тумбе для избежания дёргания изображений. Используйте для этого псевдоэлемент ‘::before’ или ‘::after’.

      • Сергей Вальдемар Ответить 13 июня 2023 в 21:20

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

      • Сергей Вальдемар Ответить 14 июня 2023 в 16:26

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

Добавить комментарий для Вальдемар

Ваш адрес email не будет опубликован. Обязательные поля помечены *