Плавное перемещение

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

Ключевые параметры камеры:

  • center — географический центр карты
  • zoom — масштаб отображения
  • bearing — угол поворота относительно севера
  • pitch — наклон камеры относительно поверхности

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


Базовые методы плавного перемещения

flyTo

Метод flyTo создаёт анимацию «перелёта» к новой точке с естественной траекторией, имитирующей движение камеры в пространстве.

map.flyTo({
  center: [66.9237, 48.0196],
  zoom: 12,
  speed: 1.2,
  curve: 1.42,
  essential: true
});

Особенности:

  • speed управляет общей скоростью анимации
  • curve определяет кривизну траектории (чем больше значение, тем более «дугообразный» полёт)
  • автоматическая адаптация зума при больших расстояниях

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


easeTo

Метод easeTo выполняет более контролируемое плавное перемещение без выраженной «трёхмерной» траектории.

map.easeTo({
  center: [66.9237, 48.0196],
  zoom: 10,
  duration: 2000,
  easing: (t) => t * (2 - t)
});

Особенности:

  • линейное или пользовательское easing-движение
  • точное управление длительностью через duration
  • отсутствие имитации полёта

Используется для интерфейсных переходов и мягких смещений карты.


jumpTo

Мгновенное перемещение камеры без анимации.

map.jumpTo({
  center: [66.9237, 48.0196],
  zoom: 8
});

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


Управление отдельными параметрами камеры

Mapbox GL JS позволяет анимировать параметры независимо друг от друга.

Центр карты

map.setCenter([66.9237, 48.0196]);

Для плавности используется:

map.easeTo({
  center: [66.9237, 48.0196],
  duration: 1500
});

Масштабирование

map.easeTo({
  zoom: 14,
  duration: 1200
});

При изменении zoom происходит интерполяция с сохранением позиции центра.


Поворот

map.easeTo({
  bearing: 90,
  duration: 2000
});

Поворот часто комбинируется с наклоном для создания эффекта 3D-навигации.


Наклон камеры

map.easeTo({
  pitch: 60,
  duration: 1800
});

Высокие значения pitch усиливают визуальную глубину сцены.


Анимация границ: fitBounds

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

map.fitBounds(
  [
    [65.0, 47.0],
    [68.0, 49.0]
  ],
  {
    padding: 40,
    duration: 2000
  }
);

Механизм:

  • вычисляется bounding box
  • подбирается оптимальный zoom
  • центрируется камера
  • учитываются отступы padding

Используется для отображения маршрутов, регионов и кластеров объектов.


Кривая анимации и easing-функции

Параметр easing определяет характер изменения прогресса анимации.

map.easeTo({
  center: [66.9, 48.0],
  duration: 2000,
  easing: (t) => Math.sin(t * Math.PI / 2)
});

Типовые варианты:

  • линейное движение: t
  • ускорение в конце: t * (2 - t)
  • синусоидальная плавность: Math.sin(...)

Кривые позволяют синхронизировать движение карты с UI-анимациями.


Прерывание и контроль анимации

Любую активную анимацию можно остановить:

map.stop();

Прерывание применяется при:

  • пользовательском взаимодействии (drag, scroll)
  • переключении сценариев навигации
  • конфликте нескольких анимационных запросов

События движения камеры

Mapbox GL JS предоставляет события для отслеживания состояния анимации:

map.on('move', () => {
  console.log('камера перемещается');
});

map.on('moveend', () => {
  console.log('перемещение завершено');
});

Дополнительные события:

  • zoom
  • rotate
  • pitch
  • idle

Событийная модель позволяет синхронизировать интерфейс с движением карты.


Плавное следование за объектом

Частый сценарий — слежение за координатами (например, GPS-трек).

function updatePosition(coords) {
  map.easeTo({
    center: coords,
    duration: 1000,
    essential: true
  });
}

Для более «жёсткого» следования используется уменьшение duration или jumpTo.


Интерактивное перемещение и инерция

При пользовательском drag-движении применяется встроенная инерция. Поведение регулируется внутренними параметрами карты:

  • deceleration
  • maxBounds
  • dragPan
  • scrollZoom

Хотя они не всегда напрямую доступны, их влияние ощущается в характере плавности взаимодействия.


Комбинирование параметров для сложной анимации

Одновременное изменение нескольких параметров камеры создаёт сложные переходы:

map.easeTo({
  center: [66.9237, 48.0196],
  zoom: 13,
  bearing: 45,
  pitch: 50,
  duration: 3000
});

Такие комбинации используются для:

  • презентации объектов
  • 3D-туров
  • навигационных сценариев

Оптимизация плавного перемещения

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

  • минимизация частоты вызовов easeTo
  • избегание конфликтующих анимаций
  • использование map.isMoving() для контроля состояния
  • ограничение сложных операций в обработчиках move

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


Управление камерой через Free Camera API

В современных версиях Mapbox GL JS доступен низкоуровневый контроль камеры:

const camera = map.getFreeCameraOptions();

camera.position = mapboxgl.MercatorCoordinate.fromLngLat(
  [66.9237, 48.0196],
  1200
);

map.setFreeCameraOptions(camera);

Этот подход позволяет:

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

Плавные переходы между состояниями карты

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

map.flyTo({
  center: [66.9, 48.0],
  zoom: 10,
  speed: 1.5
});

map.once('moveend', () => {
  map.easeTo({
    pitch: 60,
    bearing: 120,
    duration: 2000
  });
});

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