EaseTo для плавных переходов

Метод easeTo() в MapLibre GL JS предназначен для плавного перемещения камеры карты к новому состоянию. В отличие от мгновенного перехода через jumpTo(), данный метод анимирует изменение положения, масштаба, вращения и наклона карты, создавая более естественный пользовательский интерфейс.

easeTo() используется для:

  • плавного перемещения к новой точке;
  • изменения масштаба без резких скачков;
  • вращения карты;
  • изменения угла наклона;
  • комбинированной анимации нескольких параметров одновременно;
  • реализации навигационных интерфейсов и пользовательских сценариев.

Общий синтаксис выглядит следующим образом:

map.easeTo(options);

Пример:

map.easeTo({
    center: [37.6176, 55.7558],
    zoom: 12
});

После вызова карта начнёт плавно перемещаться к указанным координатам и масштабу.


Отличие easeTo() от других методов перемещения

MapLibre GL JS предоставляет несколько способов изменения положения камеры.

jumpTo()

Изменяет параметры мгновенно.

map.jumpTo({
    center: [37.6176, 55.7558],
    zoom: 12
});

Никакой анимации не происходит.


easeTo()

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

map.easeTo({
    center: [37.6176, 55.7558],
    zoom: 12
});

Перемещение выглядит естественно и комфортно для восприятия.


flyTo()

Строит более сложную траекторию движения камеры с эффектом полёта.

map.flyTo({
    center: [37.6176, 55.7558],
    zoom: 12
});

Камера не просто перемещается, а создаёт впечатление перелёта над картой.


Основные параметры easeTo()

Объект настроек может содержать множество свойств.

map.easeTo({
    center: [37.6176, 55.7558],
    zoom: 10,
    bearing: 45,
    pitch: 60,
    duration: 3000
});

Наиболее используемые параметры:

Параметр Назначение
center Новые координаты центра карты
zoom Новый уровень масштабирования
bearing Угол поворота карты
pitch Угол наклона
duration Продолжительность анимации
offset Смещение центра относительно экрана
easing Пользовательская функция сглаживания
animate Включение или отключение анимации
essential Маркировка анимации как важной

Изменение центра карты

Самый распространённый вариант использования — перемещение карты к новой точке.

map.easeTo({
    center: [30.3141, 59.9386]
});

Карта плавно переместится в район Санкт-Петербурга.


Одновременное изменение центра и масштаба

Часто требуется не только переместить карту, но и приблизить интересующую область.

map.easeTo({
    center: [30.3141, 59.9386],
    zoom: 14
});

Камера одновременно переместится и увеличит масштаб.


Управление длительностью анимации

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

map.easeTo({
    center: [30.3141, 59.9386],
    duration: 5000
});

Здесь анимация займёт пять секунд.

Более короткий переход:

map.easeTo({
    center: [30.3141, 59.9386],
    duration: 500
});

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


Изменение масштаба

Метод может использоваться исключительно для масштабирования.

Увеличение:

map.easeTo({
    zoom: 15
});

Уменьшение:

map.easeTo({
    zoom: 5
});

Карта плавно изменит масштаб относительно текущего центра.


Поворот карты

Параметр bearing отвечает за вращение карты.

map.easeTo({
    bearing: 90
});

Карта повернётся на восток.

Поворот на 180 градусов:

map.easeTo({
    bearing: 180
});

Сброс поворота

Часто используется кнопка возврата к северной ориентации.

map.easeTo({
    bearing: 0
});

После завершения анимации север снова окажется сверху.


Изменение наклона карты

Параметр pitch позволяет создать псевдотрёхмерный эффект.

map.easeTo({
    pitch: 60
});

Чем выше значение, тем сильнее наклон.

Полный пример:

map.easeTo({
    center: [37.6176, 55.7558],
    zoom: 15,
    pitch: 70
});

Одновременное изменение всех параметров камеры

Наиболее эффектные переходы получаются при комплексном изменении состояния камеры.

map.easeTo({
    center: [37.6176, 55.7558],
    zoom: 16,
    bearing: 120,
    pitch: 70,
    duration: 4000
});

В течение четырёх секунд карта:

  • переместится;
  • приблизится;
  • повернётся;
  • изменит угол наклона.

Смещение центра через offset

Иногда объект необходимо показывать не строго по центру экрана.

Например, слева может располагаться панель информации.

map.easeTo({
    center: [37.6176, 55.7558],
    offset: [250, 0]
});

Координаты будут смещены вправо относительно центра окна.


Вертикальное смещение

map.easeTo({
    center: [37.6176, 55.7558],
    offset: [0, -150]
});

Объект окажется выше центра экрана.


Пользовательские функции сглаживания

Параметр easing позволяет полностью контролировать характер анимации.

Функция получает значение времени от 0 до 1 и должна вернуть число от 0 до 1.

Простейший пример:

map.easeTo({
    center: [37.6176, 55.7558],
    duration: 3000,
    easing: t => t
});

Такой вариант создаёт линейное движение.


Ускорение в начале

map.easeTo({
    center: [37.6176, 55.7558],
    easing: t => t * t
});

Переход начинается медленно и постепенно ускоряется.


Замедление в конце

map.easeTo({
    center: [37.6176, 55.7558],
    easing: t => 1 - Math.pow(1 - t, 2)
});

Движение плавно тормозит перед завершением.


Эффект плавного ускорения и торможения

Один из наиболее популярных вариантов.

map.easeTo({
    center: [37.6176, 55.7558],
    easing: t => {
        return t < 0.5
            ? 2 * t * t
            : 1 - Math.pow(-2 * t + 2, 2) / 2;
    }
});

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


Отключение анимации

При необходимости анимацию можно отключить.

map.easeTo({
    center: [37.6176, 55.7558],
    animate: false
});

В этом случае метод будет работать аналогично jumpTo().


Использование с обработчиками событий

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

Переход по нажатию кнопки

document
    .querySelector('#moscow')
    .addEventListener('click', () => {

        map.easeTo({
            center: [37.6176, 55.7558],
            zoom: 12
        });

    });

Переход после выбора объекта

map.on('click', 'cities-layer', (event) => {

    const coordinates =
        event.features[0].geometry.coordinates;

    map.easeTo({
        center: coordinates,
        zoom: 13
    });

});

Подобный сценарий часто применяется для интерактивных справочников и геоинформационных систем.


Переход к маркеру

Предположим, на карте расположен маркер.

const marker = new maplibregl.Marker()
    .setLngLat([37.6176, 55.7558])
    .addTo(map);

При выборе объекта карта может автоматически центрироваться.

map.easeTo({
    center: marker.getLngLat(),
    zoom: 15
});

Последовательность переходов

Несколько переходов могут запускаться друг за другом.

map.easeTo({
    center: [37.6176, 55.7558],
    zoom: 10,
    duration: 3000
});

setTimeout(() => {

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

}, 3000);

Сначала произойдёт перемещение, затем вращение карты.


Отслеживание завершения анимации

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

map.once('moveend', () => {

    console.log('Переход завершён');

});

Пример с последующим действием:

map.easeTo({
    center: [37.6176, 55.7558],
    zoom: 14
});

map.once('moveend', () => {

    loadAdditionalData();

});

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


Создание кинематографических переходов

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

map.easeTo({
    center: [37.6176, 55.7558],
    zoom: 17,
    pitch: 75,
    bearing: 180,
    duration: 6000,
    easing: t => {
        return t < 0.5
            ? 4 * t * t * t
            : 1 - Math.pow(-2 * t + 2, 3) / 2;
    }
});

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


Практические сценарии применения

Навигация по списку объектов

При выборе элемента в боковой панели карта автоматически фокусируется на соответствующей точке.

map.easeTo({
    center: objectCoordinates,
    zoom: 14
});

Переход между городами

map.easeTo({
    center: cityCoordinates,
    zoom: 10,
    duration: 2500
});

Демонстрация маршрута

map.easeTo({
    center: routeCenter,
    bearing: 45,
    pitch: 60,
    duration: 4000
});

Возврат к исходному виду

map.easeTo({
    center: [37.6176, 55.7558],
    zoom: 8,
    bearing: 0,
    pitch: 0
});

Производительность и рекомендации

Избегание чрезмерно длинных анимаций

Слишком большие значения duration ухудшают восприятие интерфейса.

Неудачный вариант:

map.easeTo({
    center: point,
    duration: 15000
});

Предпочтительнее:

map.easeTo({
    center: point,
    duration: 1000
});

или

map.easeTo({
    center: point,
    duration: 2000
});

Минимизация количества одновременных вызовов

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

Проблемный код:

map.easeTo({ zoom: 10 });
map.easeTo({ zoom: 12 });
map.easeTo({ zoom: 15 });

Каждый новый вызов будет прерывать предыдущий.


Использование пользовательского сглаживания

Правильно подобранная функция easing существенно улучшает визуальное восприятие интерфейса.

Наиболее универсальным решением считается плавное ускорение и плавное торможение:

easing: t => {
    return t < 0.5
        ? 2 * t * t
        : 1 - Math.pow(-2 * t + 2, 2) / 2;
}

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