Zoom buttons и компас

В Mapbox GL JS управление масштабом карты реализовано через встроенный контрол навигации, который предоставляет пользователю стандартные кнопки увеличения и уменьшения масштаба. Эти элементы являются частью компонента NavigationControl и тесно связаны с состоянием камеры карты.

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

Подключение стандартного контроллера

Базовая интеграция осуществляется через NavigationControl:

import mapboxgl from 'mapbox-gl';

const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/streets-v12',
  center: [37.6173, 55.7558],
  zoom: 10
});

map.addControl(new mapboxgl.NavigationControl());

NavigationControl по умолчанию включает:

  • кнопки zoom-in и zoom-out
  • компас (вращение карты)
  • кнопку сброса наклона/поворота

Настройка отображения zoom-кнопок

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

map.addControl(new mapboxgl.NavigationControl({
  showZoom: true,
  showCompass: false
}));

При отключении showZoom управление масштабом остаётся доступным через:

  • жесты мыши (scroll wheel)
  • touch-жесты (pinch-to-zoom)
  • программные методы API

Поведение zoom-кнопок

Каждое нажатие изменяет масштаб на фиксированную величину, зависящую от конфигурации карты и текущего zoom:

  • zoom-in увеличивает масштаб примерно на 1
  • zoom-out уменьшает масштаб примерно на 1

Фактическая анимация выполняется плавно, с использованием интерполяции камеры.

Компас и управление направлением карты

Компас в NavigationControl отвечает за управление bearing — углом поворота карты относительно севера.

В Mapbox GL JS поворот карты — это часть камеры, а не слоя, что позволяет изменять ориентацию без пересчёта данных.

Включение и отображение компаса

map.addControl(new mapboxgl.NavigationControl({
  showCompass: true
}));

Компас отображается только при наличии ненулевого угла поворота. Если карта ориентирована на север (bearing = 0), элемент может быть скрыт или отображаться в неактивном состоянии.

Сброс ориентации

Кнопка компаса выполняет reset bearing:

map.resetNorth();

или через API камеры:

map.easeTo({
  bearing: 0,
  pitch: 0
});

Сброс сопровождается анимацией, возвращающей карту в стандартную ориентацию.

Взаимодействие zoom и bearing

Zoom и rotation в Mapbox GL JS работают независимо, но оба влияют на восприятие карты пользователем:

  • zoom изменяет масштаб отображения данных
  • bearing изменяет ориентацию сцены
  • pitch добавляет трёхмерный наклон

Комбинация этих параметров формирует камеру WebGL-сцены, которая перерисовывается в реальном времени.

Пример комбинированного управления:

map.easeTo({
  zoom: 14,
  bearing: 45,
  pitch: 60,
  duration: 2000
});

Программное управление zoom-кнопками

Хотя zoom-кнопки являются UI-элементами, их функциональность полностью дублируется API:

map.zoomIn();
map.zoomOut();

Существует также контроль перехода к конкретному уровню:

map.setZoom(12);

Эти методы позволяют синхронизировать внешние интерфейсы с состоянием карты.

События изменения масштаба и ориентации

Для отслеживания взаимодействий используются события карты:

map.on('zoom', () => {
  console.log(map.getZoom());
});

map.on('zoomend', () => {
  console.log('zoom завершён');
});

map.on('rotate', () => {
  console.log(map.getBearing());
});

События позволяют:

  • синхронизировать UI
  • обновлять данные в зависимости от масштаба
  • логировать пользовательскую активность

Расположение zoom и компаса на карте

NavigationControl можно размещать в любом углу контейнера:

map.addControl(
  new mapboxgl.NavigationControl(),
  'top-right'
);

Доступные позиции:

  • top-right
  • top-left
  • bottom-right
  • bottom-left

Выбор позиции влияет на UX в зависимости от плотности интерфейса.

Кастомизация внешнего вида

Стилизация zoom-кнопок возможна через CSS:

.mapboxgl-ctrl button {
  width: 36px;
  height: 36px;
  border-radius: 6px;
}

.mapboxgl-ctrl-zoom-in,
.mapboxgl-ctrl-zoom-out {
  font-size: 18px;
}

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

Поведение на мобильных устройствах

На мобильных устройствах zoom-кнопки часто считаются вспомогательными, поскольку основной способ управления — жесты:

  • pinch-to-zoom
  • double-tap zoom
  • rotate gesture

NavigationControl при этом может быть упрощён или полностью скрыт, чтобы не дублировать естественные жесты.

Интеграция с кастомными контролами

NavigationControl можно комбинировать с пользовательскими элементами управления:

class CustomZoomControl {
  onAdd(map) {
    this.map = map;
    this.container = document.createElement('div');

    const btn = document.createElement('button');
    btn.textContent = '+';
    btn.oncl ick = () => map.zoomIn();

    this.container.appendChild(btn);
    return this.container;
  }

  onRemove() {
    this.container.parentNode.removeChild(this.container);
    this.map = undefined;
  }
}

map.addControl(new CustomZoomControl());

Такая схема позволяет полностью заменить стандартный UI, сохраняя API-совместимость.

Доступность и управление с клавиатуры

Zoom-кнопки поддерживают базовые принципы accessibility:

  • фокусировка через Tab
  • активация через Enter/Space
  • корректные aria-атрибуты

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

Ограничение диапазона масштаба

Zoom-кнопки подчиняются ограничениям карты:

const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/streets-v12',
  minZoom: 5,
  maxZoom: 18
});

Даже при многократных кликах выход за пределы диапазона невозможен, что предотвращает некорректную загрузку тайлов и перегрузку WebGL-контекста.