В этом уроке мы собираемся создать простую JavaScript библиотеку для добавления эффекта увеличения изображения. Мы создадим всю библиотеку с нуля, не полагаясь на jQuery или любые другие внешние зависимости. Давайте приступим!
Проект
Вы можете увидеть этот эффект во многих интернет магазинах, включая очень популярные, такие как eBay и Amazon. Этот эффект обычно состоит из группы небольших фотографий, которые можно увеличчить и дополнительно инспектировать с помощью лупы.
Чтобы упростить статью, мы не будем добавлять слишком много функций в библиотеку. Он будет содержать только один файл JavaScript, а также CSS файл для быстрого создания галереи, подобной приведенной выше.
Проектирование библиотеки
Прежде чем мы начнем создавать библиотеку, давайте разберем, как люди будут ее использовать. Решение этого вопроса в самом начале облегчит нам разработку библиотеки в дальнейшем.
Поскольку мы создаем плагин галереи, то при его использовании необходим шаблонный HTML-код. Этот шаблон будет содержать блок div
с изображениями, пустой div
для эффекта масштабирования, а также предопределенные классы для работы библиотеки.
1 2 3 4 5 6 7 8 |
<div id="my-gallery" class="vanilla-zoom"> <div class="sidebar"> <img src="images/image-1.jpg" class="small-preview"> <img src="images/image-2.jpg" class="small-preview"> <img src="images/image-3.jpg" class="small-preview"> </div> <div class="zoomed-image"></div> </div> |
Можно изменять этот макет, добавляя любое количество изображений. Важно, однако, чтобы каждое изображение имело класс .small-preview
и наличие пустого блока div с классом.zoomed-image
.
Библиотека будет под управлением JavaScript, но есть несколько важных CSS стилей, которые необходимо установить и подключить наш CSS-файл непосредственно в HTML-код.
1 |
<link rel="stylesheet" href="vanilla-zoom/vanilla-zoom.css"> |
Теперь, когда разметка и стили установлены, все, что осталось, это подключить библиотеку и инициализировать ее.
1 2 3 4 |
<script src="vanilla-zoom/vanilla-zoom.js"></script> <script> vanillaZoom.init('#my-gallery'); </script> |
Подключение файла .js библиотеки делает объект vanillaZoom
доступным глобально. Объект имеет только один метод, который предназначен для инициализации плагина. Он принимает один параметр — идентификатор нашей галереи. Таким образом, у нас может быть несколько независимых галерей, инициализированных на одной странице.
Разработка библиотеки
При создании фронтенд библиотек на JavaScript нам необходимо убедиться, что мы правильно зарегистрировали их API. Существует много способов сделать это, возможно, самым простым из которых является этот метод Джордана Чекмана. Вкратце способ сводится к следующему:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
(function(window) { function define_library() { // Создаем объект библиотеки и все его свойства и методы. var vanillaZoom = {}; vanillaZoom.init = function(galleryId) { // Ниже идет логика нашей библиотеки. } return vanillaZoom; } // Добавить объект vanillaZoom в глобальную область видимости, если он еще не определен. if(typeof(vanillaZoom) === 'undefined') { window.vanillaZoom = define_library(); } else{ console.log("Library already defined."); } })(window); |
Вышеупомянутый код завернут в функцию самоисполнения. Таким образом, когда мы добавим файлvanilla-zoom.js
в наш проект, библиотека будет автоматически зарегистрирована, и объект vanillaZoom
со всеми его методами станет доступным для пользователя.
В нашей библиотеке есть только один метод — vanillaZoom.init(galleryId)
. Его задача — выбрать элементы DOM галереи и добавить к ним прослушиватели событий (event listeners).
Сначала мы проверяем, добавлены ли элементы в HTML правильно и выбираем их. Мы не можем использовать jQuery, поэтому для работы с DOM нам приходится полагаться на нативные методы JavaScript.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
var container = document.querySelector(el); if(!container) { console.error('Укажите правильный класс вашей галереи'); return; } var firstSmallImage = container.querySelector('.small-preview'); var zoomedImage = container.querySelector('.zoomed-image'); if(!zoomedImage) { console.error('Пожалуйста, добавьте элемент .zoomed-image в вашу галерею'); return; } if(!firstSmallImage) { console.error('Пожалуйста, добавьте изображения с классом .small-preview в вашу галерею'); return; } else { // Устанавливаем источник увеличенного изображения. zoomedImage.style.backgroundImage = 'url('+ firstSmallImage.src +')'; } |
В последней строке приведенного выше кода мы берем источник изображения одного из изображений в предварительном просмотре и устанавливаем его как фон нашего масштабируемого элемента. Это происходит сразу после вызова vanillaZoom.init(galleryId)
, для того чтобы наша галерея не была пустой.
Мы делаем то же самое при клике на превью изображения. Это позволяет пользователю выбирать, какое изображение он хочет увеличить.
1 2 3 4 5 6 7 |
container.addEventListener("click", function (event) { var elem = event.target; if (elem.classList.contains("small-preview")) { zoomedImage.style.backgroundImage = 'url('+ elem.src +')'; } }); |
Элемент лупы содержит два прикрепленных к нему прослушивателя событий. Первый активируется, когда курсор находится поверх элемента и увеличивает размер фонового изображения, тем самым создавая эффект масштабирования.
1 2 3 |
zoomedImage.addEventListener('mouseenter', function(e) { this.style.backgroundSize = "250%"; }, false); |
Поскольку изображение теперь очень большое, оно не будет вписываться в контейнер, и видна будет только его часть. Мы хотим, чтобы пользователь мог выбирать, какая часть изображения будет увеличена, поэтому мы добавляем слушатель mousemove
, который меняет положение фона.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
zoomedImage.addEventListener('mousemove', function(e) { // getBoundingClientRect дает нам различную информацию о позиции элемента. var dimentions = this.getBoundingClientRect(); // Вычислить положение курсора внутри элемента (в пикселях). var x = e.clientX - dimentions.left; var y = e.clientY - dimentions.top; // Вычислить положение курсора в процентах от общего размера элемента. var xpercent = Math.round(100 / (dimentions.width / x)); var ypercent = Math.round(100 / (dimentions.height / y)); // Обновление фоновой позиции изображения. this.style.backgroundPosition = xpercent+'% ' + ypercent+'%'; }, false); |
Когда курсор покидает область увеличенного изображения, мы хотим, чтобы изображение вернулось в обратное состояние. Это легко сделать, возвращая для background size — cover
и для background position — center
.
1 2 3 4 |
zoomedImage.addEventListener('mouseleave', function(e) { this.style.backgroundSize = "cover"; this.style.backgroundPosition = "center"; }, false); |
И на этом все!
Поддержка браузера
Библиотека будет работать во всех современных десктоп браузерах, хотя некоторые из flexbox CSS могут отображаться некорректно в старых версиях IE.
К сожалению, эффект масштабирования не очень хорошо подходит для сенсорных устройств. Также изза ограниченного пространства экрана на мобильных устройствах лучше представлять свои изображения по-другому. В нашем CSS мы просто спрятали элемент масштабирования и отобразили изображения по вертикали листингом, но вы можете попробовать другие решения, например карусель.
Вывод
Вы можете скачать полный исходный код этой статьи, соответствующий демо коду (изображения любезно взяты из Burst), с помощью кнопки «Скачать» в верхней части страницы. Вы можете использовать библиотеку во всех своих проектах, коммерческих или личных.Счастливого кодинга!
Не совсем точный перевод статьи на tutorialzine.com