Управление камерой программно

Mapbox GL JS построен вокруг модели «камеры», которая определяет текущее состояние отображения карты: центр, масштаб, наклон, поворот и границы видимой области. Камера не является визуальным объектом в привычном смысле, а представляет собой абстракцию трансформации сцены WebGL, где вся карта рассматривается как плоскость в трёхмерном пространстве.

Mapbox предоставляет низкоуровневую графическую модель, в которой управление камерой становится ключевым способом взаимодействия с картой. Любое перемещение, масштабирование или вращение реализуется через изменение параметров камеры, а не через прямую манипуляцию DOM.


Состояние камеры в Mapbox GL JS определяется несколькими фундаментальными параметрами:

  • center — координаты центра карты (долгота, широта)
  • zoom — уровень масштабирования
  • bearing — угол поворота карты относительно севера
  • pitch — наклон камеры относительно поверхности

Эти параметры можно задавать как одновременно, так и по отдельности.

map.setCenter([37.6173, 55.7558]);
map.setZoom(10);
map.setBearing(30);
map.setPitch(45);

Эквивалентная операция через единый объект камеры:

map.setCenter({
  center: [37.6173, 55.7558],
  zoom: 10,
  bearing: 30,
  pitch: 45
});

Прямое позиционирование камеры

Метод jumpTo изменяет состояние камеры мгновенно, без анимации. Он используется в случаях, когда требуется синхронное обновление вида.

map.jumpTo({
  center: [30.3351, 59.9343],
  zoom: 12,
  bearing: 0,
  pitch: 0
});

Характеристика jumpTo:

  • отсутствует интерполяция
  • изменение происходит в текущем кадре
  • подходит для мгновенных переключений состояния

Анимационное управление камерой

easeTo

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

map.easeTo({
  center: [2.3522, 48.8566],
  zoom: 11,
  duration: 2000,
  easing: (t) => t * (2 - t)
});

Основные параметры:

  • duration — длительность анимации в миллисекундах
  • easing — функция интерполяции
  • offset — смещение центра в пикселях
  • animate — включение/выключение анимации

Математическая модель основана на линейной интерполяции с применением easing-функции к временной шкале.


flyTo

flyTo реализует физически имитированное перемещение камеры с «полётом» к цели. Используется для навигационных переходов между удалёнными точками.

map.flyTo({
  center: [139.6917, 35.6895],
  zoom: 12,
  speed: 1.2,
  curve: 1.5,
  essential: true
});

Параметры:

  • speed — скорость перемещения (условная единица)
  • curve — кривизна траектории
  • maxDuration — ограничение длительности
  • essential — игнорирование prefers-reduced-motion

Особенность flyTo заключается в нелинейной траектории: камера сначала поднимается, затем перемещается по дуге и опускается к цели.


Подгонка области видимости

fitBounds

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

map.fitBounds([
  [30.0, 59.0],
  [31.0, 60.0]
], {
  padding: 40,
  maxZoom: 14,
  duration: 1500
});

Алгоритм учитывает:

  • текущие пропорции контейнера
  • ограничение zoom
  • padding (внутренние отступы)
  • возможные ограничения maxBounds

Ограничения движения камеры

Камера может быть ограничена в пределах заданной области.

maxBounds

map.setMaxBounds([
  [29.0, 58.0],
  [32.0, 61.0]
]);

Поведение:

  • запрет выхода центра за границы
  • автоматическая коррекция при попытке перемещения
  • применяется ко всем методам перемещения камеры

minZoom и maxZoom

map.setMinZoom(5);
map.setMaxZoom(18);

Эти ограничения предотвращают чрезмерное приближение или отдаление, сохраняя визуальную стабильность слоя тайлов.


Работа с состоянием камеры

Текущее состояние камеры извлекается через методы чтения:

const center = map.getCenter();
const zoom = map.getZoom();
const bearing = map.getBearing();
const pitch = map.getPitch();

Полный объект состояния:

const cameraState = map.getCameraOptions();

Эти данные используются для:

  • синхронизации интерфейсов
  • сохранения состояния
  • построения пользовательских контролов

События изменения камеры

Изменение камеры сопровождается набором событий:

  • movestart
  • move
  • moveend
  • zoomstart
  • zoom
  • zoomend
  • rotatestart
  • rotate
  • rotateend
  • pitchstart
  • pitch
  • pitchend
map.on('move', () => {
  const c = map.getCenter();
});

Семантика событий:

  • start — начало трансформации
  • без суффикса — процесс изменения
  • end — завершение анимации или взаимодействия

Одновременное управление несколькими параметрами

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

map.easeTo({
  center: [13.4050, 52.5200],
  zoom: 13,
  pitch: 60,
  bearing: 120,
  duration: 2500
});

Такой подход позволяет формировать «сценические переходы», где одновременно изменяется перспектива, масштаб и направление обзора.


Интеракции пользователя и программное управление

Программное управление камерой взаимодействует с пользовательскими жестами:

  • drag
  • scroll zoom
  • pinch zoom
  • rotate gesture

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

  • прерывать пользовательскую анимацию
  • продолжать текущую интерполяцию
  • переопределять конечное состояние

Easing-функции и контроль анимации

Easing определяет характер движения камеры во времени.

(t) => t * t

Типовые формы:

  • линейная интерполяция
  • квадратическая
  • кубическая
  • синусоидальная

Контроль easing критичен для визуальной согласованности переходов между сценами карты.


Пиксельные смещения камеры

Параметр offset позволяет смещать центр относительно контейнера:

map.easeTo({
  center: [10, 50],
  offset: [100, 0]
});

Это используется для:

  • компенсации UI-панелей
  • выделения объектов
  • создания эффектов «следования»

Камера и перспективная проекция

При наличии pitch карта переходит в режим перспективного отображения. Геометрия тайлов пересчитывается в трёхмерном пространстве, где:

  • zoom влияет на масштаб сцены
  • pitch задаёт угол обзора
  • bearing определяет поворот вокруг оси Z

Комбинация этих параметров формирует полноценную 3D-сцену на основе 2D-данных.


Программная синхронизация состояния камеры

Состояние камеры часто используется как источник истины для внешних систем:

  • URL-синхронизация (hash routing)
  • хранение в localStorage
  • обмен между компонентами UI
  • репликация состояния в реальном времени
map.on('moveend', () => {
  const state = {
    center: map.getCenter(),
    zoom: map.getZoom()
  };
});

Приоритеты анимаций

При одновременных вызовах методов камеры действует система приоритетов:

  1. jumpTo — мгновенное переопределение
  2. easeTo — стандартная анимация
  3. flyTo — физически моделируемое перемещение
  4. пользовательские жесты — могут перехватывать управление

Это определяет поведение при конфликте входящих команд трансформации сцены.