Frontend-разработчик в Foquz.
https://www.cat-in-web.ru/
Чтобы не использовать тяжеловесные библиотеки, можно написать на чистом JavaScript простое и расширяемое решение для манипуляций с элементами веб-страницы.
Возможность масштабировать элементы страницы и детально рассматривать их – это очень крутой пользовательский опыт. Существует множество готовых библиотек с подобной функциональностью, но сегодня мы напишем собственный велосипед на чистом JavaScript! Зачем?
Сторонние решения часто предлагают избыточную функциональность, которая вам не нужна, но бандл приложения увеличивает.
К тому же это замечательный челлендж, который расшевелит ваш мозг и прокачает навыки программирования.
В результате мы получим очень маленькую (всего 69 строчек кода!), простую и удобную библиотечку для масштабирования и панорамирования.
Разметка и стили
Создадим HTML-страницу и разместим на ней элемент-контейнер (#container). Внутрь поместим рабочую область (.area), которую мы и будем непосредственно масштабировать и панорамировать.
Внутри рабочей области находятся несколько элементов, которые не несут никакой смысловой нагрузки, а просто предназначены для демонстрации работы кода.
Добавим также немного стилей для оформления страницы:
Для body устанавливаем overflow: hidden. Это нужно, чтобы избежать переполнения страницы и появления прокрутки при чрезмерном увеличении элемента.
Также добавим рамку для визуального обозначения рабочей области (.area) и немного облагородим демо-контент (классы .circle, .rectangle и .text-area).
Скрипт библиотеки
Код самой библиотеки будет располагаться в файле renderer.js. Экспортируем из модуля главную функцию renderer:
Она принимает базовые параметры:
minScale – минимальный масштаб;
maxScale – максимальный масштаб;
element – DOM-элемент, с которым будут производиться манипуляции;
scaleSensitivity – коэффициент чувствительность масштабирования, по умолчанию 10.
В замыкании функции создается объект состояния – state, который хранит настройки и совершенные над элементом преобразования (поле transformation).
Из функции возвращается объект с набором методов. При этом возможности масштабирования и панорамирования разделены на отдельные функции-конструкторы – makeZoom и makePan, которые мы разберем чуть позже. Конструкторы получают общий объект состояния и возвращают отдельный набор методов для взаимодействия с ним.
Такой подход называется композицией и позволяет проще добавлять новую функциональность и легче тестировать приложение.
Трансформации
Все манипуляции с элементом будут производиться через изменение свойства transform. Для этого используем CSS-функцию matrix, которой нужно передать правильные параметры масштаба (scale) и сдвига (translateX и translateY):
Вспомогательная функция getMatrix просто формирует шаблонную строку правильного формата, которую нужно установить в свойство style.transform элемента.
Панорамирование
При панорамировании должно изменяться положение элемента на странице, то есть производиться его сдвиг. Функция pan принимает текущее состояние элемента (state), а также новые координаты. Затем она обновляет состояние, прибавляя новый сдвиг к текущему положению и обновляет свойство style элемента.
Теперь реализуем два метода:
panBy – простой сдвиг на указанные координаты;
panTo – сдвиг с одновременным масштабированием.
При сдвиге с масштабированием координаты элемента нужно скорректировать.
Масштабирование
Для изменения размера элемента нам потребуется несколько вспомогательных функций для расчетов:
Метод getScale рассчитывает новый масштаб на основе предыдущего значения, минимального и максимального ограничений (minScale, maxScale) и коэффициентов (scaleSensitivity, deltaScale).
Метод getTranslate рассчитывает новый сдвиг на основе масштаба и текущей и предыдущей позиции.
А вот и реализация функции makeZoom:
Она возвращает только один метод zoom, предназначенный для масштабирования элемента. Он получает координаты курсора, а также параметр deltaScale – коэффициент, который определяет направление масштабирования (1 для увеличения, -1 для уменьшения).
Функция вычисляет новые параметры трансформации и обновляет свойство style элемента.
При масштабировании кроме style.transform нужно изменять также свойство style.transformOrigin, чтобы скорректировать позицию элемента. В качестве эксперимента вы можете закомментировать 14 строчку и посмотреть, что будет.
Главный файл
Кроме того мы сделаем главный файл приложения index.js:
Клиентский код создает экземпляр renderer и передает ему базовую конфигурацию:
элемент, размер которого будет изменяться;
минимальный и максимальный масштаб;
коэффициент чувствительности масштабирования.
Затем устанавливаются слушатели событий мыши и в нужный момент вызываются нужные методы:
для масштабирования используйте колесико мыши или сенсорную панель, зажав клавишу CTRL.
для перемещения – перемещайте мышь или используйте тачпад, зажав клавишу SHIFT.
Двойной щелчок мыши восстановит исходное состояние элемента.
Демо-пример:
Тестирование
Проверим реализованные функции с помощью библиотеки Mocha:
Перед каждым тестом (beforeEach) создается объект _element с дефолтными значениями.
Кейсы тестирования для удобства вынесены в отдельный файл renderer.testCases.js.
***
В итоге у нас получился очень простой и удобный инструмент для масштабирования и панорамирования на JavaScript, состоящий всего из 69 строк кода. Его можно сократить больше, но не хочется терять читабельность.
Комментарии