Камера в MapLibre GL JS определяет положение виртуального наблюдателя относительно карты. Через параметры камеры управляются центр карты, масштаб, наклон и поворот. Плавная анимация камеры позволяет создавать естественные переходы между состояниями карты без резких скачков интерфейса.
Анимация применяется в различных сценариях:
Состояние камеры определяется несколькими ключевыми характеристиками:
| Параметр | Описание |
|---|---|
center |
Географический центр карты |
zoom |
Уровень масштабирования |
bearing |
Поворот карты относительно севера |
pitch |
Угол наклона карты |
Пример начальной конфигурации:
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [37.6176, 55.7558],
zoom: 10,
bearing: 0,
pitch: 0
});
Наиболее популярный способ плавного перемещения камеры —
использование метода flyTo().
Пример перелёта к новой точке:
map.flyTo({
center: [30.3351, 59.9343],
zoom: 12
});
Камера выполнит анимированный переход от текущего положения к указанным координатам.
Метод моделирует эффект полёта над картой:
Пример:
map.flyTo({
center: [2.3522, 48.8566],
zoom: 13
});
Если текущий центр находится в Москве, пользователь увидит плавный перелёт к Парижу.
Параметр duration задаёт длительность анимации в
миллисекундах.
map.flyTo({
center: [2.3522, 48.8566],
zoom: 13,
duration: 5000
});
В данном случае анимация займёт пять секунд.
Часто используемые значения:
| Значение | Эффект |
|---|---|
| 500 | Очень быстро |
| 1000 | Быстро |
| 2000 | Стандартный переход |
| 5000+ | Демонстрационный режим |
Параметр speed влияет на скорость движения камеры.
map.flyTo({
center: [13.4050, 52.5200],
zoom: 12,
speed: 0.5
});
По умолчанию используется значение около 1.2.
Чем больше значение:
map.flyTo({
center: [13.4050, 52.5200],
zoom: 12,
speed: 3
});
тем быстрее камера достигнет цели.
curve определяет форму траектории полёта.
map.flyTo({
center: [13.4050, 52.5200],
zoom: 12,
curve: 2
});
Большие значения создают более выраженную дугу движения.
Небольшие значения дают более прямолинейный переход.
Для более контролируемых перемещений используется
easeTo().
map.easeTo({
center: [37.64, 55.76],
zoom: 14
});
Отличия от flyTo:
| flyTo | easeTo |
|---|---|
| Эффект полёта | Простое плавное движение |
| Подходит для больших расстояний | Подходит для локальных перемещений |
| Может менять масштаб автоматически | Обычно выполняет прямой переход |
Изменение масштаба без перемещения:
map.easeTo({
zoom: 15
});
Уменьшение масштаба:
map.easeTo({
zoom: 5
});
Подобные переходы часто используются при выборе объектов из списка.
Камера может изменять несколько характеристик одновременно.
map.easeTo({
center: [37.6176, 55.7558],
zoom: 16,
bearing: 90,
pitch: 60,
duration: 3000
});
В результате карта:
Для анимации поворота используется свойство bearing.
map.easeTo({
bearing: 180,
duration: 2000
});
Карта плавно развернётся в противоположную сторону.
Сброс поворота:
map.easeTo({
bearing: 0
});
Наклон создаёт эффект перспективы.
map.easeTo({
pitch: 60
});
Максимально допустимый угол зависит от версии движка и настроек карты.
Возврат к виду сверху:
map.easeTo({
pitch: 0
});
Часто требуется переместить камеру к выбранному маркеру.
marker.getElement().addEventListener('click', () => {
map.flyTo({
center: marker.getLngLat(),
zoom: 15
});
});
После нажатия карта плавно переместится к объекту.
Для анимации перехода к области применяется
fitBounds().
const bounds = [
[37.50, 55.70],
[37.75, 55.85]
];
map.fitBounds(bounds, {
padding: 50
});
Камера автоматически рассчитает оптимальный масштаб и центр.
Метод поддерживает анимацию.
map.fitBounds(bounds, {
padding: 50,
duration: 3000
});
Переход будет выполнен плавно в течение трёх секунд.
После завершения одной анимации можно запускать следующую.
map.flyTo({
center: [37.6176, 55.7558],
zoom: 12,
duration: 3000
});
map.once('moveend', () => {
map.easeTo({
pitch: 60,
bearing: 120,
duration: 2000
});
});
Сначала выполняется перелёт, затем изменение угла обзора.
Запускается при начале движения камеры.
map.on('movestart', () => {
console.log('Начало движения');
});
Вызывается во время анимации.
map.on('move', () => {
console.log('Камера движется');
});
Срабатывает после завершения движения.
map.on('moveend', () => {
console.log('Движение завершено');
});
Любое действие пользователя может остановить текущую анимацию.
Например:
Для программного прерывания используется:
map.stop();
Пример:
map.flyTo({
center: [2.3522, 48.8566],
duration: 10000
});
setTimeout(() => {
map.stop();
}, 3000);
Анимация завершится через три секунды после запуска.
Один из популярных сценариев — экскурсия по нескольким городам.
const locations = [
[37.6176, 55.7558],
[30.3351, 59.9343],
[39.7015, 47.2357]
];
let index = 0;
function flyNext() {
map.flyTo({
center: locations[index],
zoom: 12,
duration: 4000
});
index++;
if (index < locations.length) {
map.once('moveend', flyNext);
}
}
flyNext();
Камера будет последовательно перелетать между заданными координатами.
Сочетание наклона, поворота и изменения масштаба позволяет создавать эффектные сцены.
map.flyTo({
center: [37.6176, 55.7558],
zoom: 17,
pitch: 70,
bearing: 120,
duration: 6000
});
Подобный подход используется:
Камера может постоянно перемещаться вслед за объектом.
function updateVehicle(position) {
map.easeTo({
center: position,
duration: 500
});
}
При регулярном обновлении координат создаётся эффект сопровождения объекта.
При большом количестве перемещений важно избегать запуска новой анимации до завершения предыдущей.
Плохой вариант:
setInterval(() => {
map.easeTo({
center: getPosition()
});
}, 100);
Лучше использовать более редкие обновления:
setInterval(() => {
map.easeTo({
center: getPosition(),
duration: 1000
});
}, 1000);
Либо проверять состояние приложения перед запуском очередной анимации.
Анимации часто связываются с элементами управления.
Кнопка перехода:
button.addEventListener('click', () => {
map.flyTo({
center: [37.6176, 55.7558],
zoom: 14
});
});
Выбор элемента списка:
list.addEventListener('change', (event) => {
map.flyTo({
center: getCoordinates(event.target.value),
zoom: 15
});
});
Такой подход позволяет создавать интерактивную навигацию по данным карты.
Для дальних перемещений предпочтителен
flyTo().
Для локальных изменений камеры обычно используется
easeTo().
Продолжительность анимации желательно удерживать в диапазоне от 1000 до 3000 миллисекунд для большинства интерфейсов.
Наклон и поворот следует применять умеренно, чтобы не ухудшать ориентацию пользователя на карте.
Длинные цепочки анимаций лучше строить через события
moveend.
Принудительное сопровождение объектов не должно полностью лишать пользователя возможности самостоятельно управлять картой.
Анимации камеры должны подчёркивать структуру геоданных и облегчать навигацию, а не превращаться в декоративный элемент интерфейса.