Камера в MapLibre GL JS представляет собой абстракцию состояния отображения карты, включающую центр, масштаб, угол поворота и наклон. Управление камерой сводится к изменению этих параметров с возможностью анимации, интерполяции и прерывания переходов. Все методы камеры опираются на единый принцип: переход от текущего состояния к целевому с заданными параметрами времени и кривой интерполяции.
Состояние камеры определяется набором свойств:
Любое изменение этих параметров может быть выполнено мгновенно либо с анимацией. Анимационные переходы реализуются через встроенный tweening-механизм.
Ключевые параметры анимации:
Метод jumpTo выполняет моментальный переход без
анимации. Он используется в случаях, когда визуальная интерполяция не
требуется.
map.jumpTo({
center: [30.31413, 59.93863],
zoom: 10,
bearing: 0,
pitch: 0
});
Изменения применяются сразу, без промежуточных кадров, что делает метод полезным для синхронизации состояния карты с внешними событиями.
Метод easeTo реализует плавное изменение камеры с
контролируемой кривой ускорения и замедления.
map.easeTo({
center: [30.31413, 59.93863],
zoom: 12,
duration: 2000,
easing: (t) => t * (2 - t)
});
Параметр easing принимает функцию, нормализованную на
диапазон от 0 до 1, где значение определяет прогресс анимации.
Использование нелинейных функций позволяет создавать эффект ускорения,
замедления или комбинированного движения.
Типовая сигнатура easing-функции:
function easing(t) {
return t;
}
Для более сложных траекторий применяются квадратичные, кубические и синусоидальные функции.
Метод flyTo реализует анимацию с эффектом «полёта» к
целевой точке. В отличие от easeTo, движение включает
дугообразную траекторию и динамическое изменение масштаба.
map.flyTo({
center: [37.6173, 55.7558],
zoom: 13,
speed: 1.2,
curve: 1.5,
essential: true
});
Параметры:
Алгоритм строит интерполяцию не по линейной прямой, а по геодезической дуге, что создаёт визуальный эффект «перелёта» над картой.
Любая активная анимация камеры может быть прервана методом
stop.
map.stop();
После вызова текущее состояние фиксируется, а дальнейшие переходы требуют нового вызова методов управления камерой. Это важно при обработке пользовательского взаимодействия, чтобы исключить конфликт автоматической и ручной навигации.
Отдельные параметры камеры могут изменяться независимо.
map.rotateTo(90, { duration: 1000 });
map.pitchTo(45, {
duration: 1500,
easing: (t) => Math.pow(t, 2)
});
rotateTo управляет вращением вокруг центра, а
pitchTo изменяет угол обзора. Оба метода поддерживают
анимацию и easing-функции.
Метод fitBounds обеспечивает автоматическое
позиционирование камеры таким образом, чтобы указанный географический
прямоугольник полностью помещался в область видимости.
map.fitBounds(
[[30.0, 59.8], [30.5, 60.1]],
{
padding: 40,
duration: 2000
}
);
Алгоритм вычисляет оптимальный zoom и center, учитывая пропорции контейнера карты.
Все анимации камеры в MapLibre GL JS основаны на временной
интерполяции. Для каждого кадра вычисляется прогресс t в
диапазоне [0, 1], после чего применяются функции интерполяции:
Обобщённая модель:
state = start + (end - start) * easing(t);
Для zoom применяется логарифмическое преобразование, обеспечивающее равномерное восприятие масштаба.
При запуске новой анимации предыдущая может быть автоматически прервана. Поведение зависит от метода:
easeTo и flyTo прерывают текущую
анимациюjumpTo мгновенно заменяет состояниеstop фиксирует текущее состояние без переходаКонкуренция анимаций становится критичной при быстром поступлении событий, например при скролле или обновлении данных в реальном времени.
Изменения камеры сопровождаются событиями:
movestartmovemoveendzoomstartzoomzoomendrotatestartrotaterotateendПример последовательности:
map.on('movestart', () => {
console.log('движение началось');
});
map.on('moveend', () => {
console.log('движение завершено');
});
Эти события позволяют синхронизировать внешние компоненты с состоянием камеры.
Камера может быть связана с координатами объекта, обновляемыми в
реальном времени. В таком режиме используется непрерывное обновление
center.
function updatePosition(lng, lat) {
map.easeTo({
center: [lng, lat],
duration: 500
});
}
При высокой частоте обновлений применяется оптимизация через
requestAnimationFrame, чтобы избежать перегрузки
анимационного цикла.
Вращение камеры вокруг точки реализуется через изменение
bearing во времени.
function spinCamera(timestamp) {
const rotation = timestamp / 100;
map.rotateTo(rotation % 360, { duration: 0 });
requestAnimationFrame(spinCamera);
}
requestAnimationFrame(spinCamera);
Такой подход создаёт непрерывную анимацию без использования встроенных tween-методов.
Сложные сценарии камеры часто включают одновременное изменение нескольких параметров:
map.flyTo({
center: [37.6173, 55.7558],
zoom: 14,
pitch: 60,
bearing: -30,
duration: 3000
});
Комбинация параметров формирует многомерную интерполяцию, где каждый компонент изменяется по собственной кривой, синхронизированной по времени.
Производительность зависит от частоты кадров и сложности сцены. Основные факторы:
Для стабильной анимации ограничивается частота вызовов методов изменения камеры и избегаются избыточные пересчёты состояния.
Последовательные переходы реализуются через цепочку вызовов:
map.flyTo({
center: [30.3, 59.9],
zoom: 10,
duration: 2000
});
map.once('moveend', () => {
map.easeTo({
zoom: 14,
duration: 1500
});
});
Такая модель позволяет строить сценарии навигации с детерминированной последовательностью кадров без внешнего таймера.