Анимация viewport

Базовая модель управления состоянием камеры

В Deck.gl вся логика отображения сцены напрямую связана с понятием viewport (окна просмотра), которое определяется через объект viewState. Он описывает положение камеры, масштаб, угол наклона и ориентацию сцены.

Ключевая идея: любое движение карты или 3D-сцены — это изменение viewState, которое может происходить мгновенно или с анимацией.

Основные параметры viewState для MapView:

  • longitude — долгота центра
  • latitude — широта центра
  • zoom — уровень приближения
  • bearing — поворот карты
  • pitch — наклон камеры

Пример базового состояния:

const INITIAL_VIEW_STATE = {
  longitude: 37.6173,
  latitude: 55.7558,
  zoom: 10,
  bearing: 0,
  pitch: 0
};

Любое изменение этих параметров может быть интерпретировано как мгновенное или анимированное перемещение камеры.


Механизм обновления viewState

DeckGL использует реактивную модель: каждый кадр сцена пересчитывается на основе текущего viewState. Управление осуществляется через:

<DeckGL
  initialViewState={INITIAL_VIEW_STATE}
  controller={true}
  onViewStateCha nge={({ viewState }) => {
    // обновление состояния
  }}
/>

При включённом controller, пользовательские действия (панорамирование, зум, вращение) автоматически генерируют новые viewState.

Анимация появляется тогда, когда изменения состояния интерполируются во времени, а не применяются напрямую.


Принцип анимации viewport

Анимация в Deck.gl основана на интерполяции параметров камеры между начальным и конечным состоянием.

Общая модель:

viewState(t) = interpolate(startViewState, endViewState, easing(t))

где:

  • t — прогресс анимации от 0 до 1
  • easing(t) — функция сглаживания
  • interpolate — линейная или специализированная интерполяция

Для разных параметров применяются разные стратегии:

  • координаты (latitude/longitude) — линейная интерполяция
  • zoom — экспоненциальная интерполяция
  • bearing/pitch — угловая интерполяция с нормализацией

Transition API в Deck.gl

Deck.gl предоставляет встроенный механизм анимации через свойства переходов:

const viewState = {
  longitude: 37.6173,
  latitude: 55.7558,
  zoom: 12,
  transitionDuration: 2000,
  transitionInterpolator: new FlyToInterpolator(),
  transitionEasing: t => t
};

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

transitionDuration

  • длительность анимации в миллисекундах
  • определяет скорость перехода между состояниями

transitionInterpolator

  • объект, отвечающий за математическую модель интерполяции
  • управляет тем, как именно камера перемещается

transitionEasing

  • функция сглаживания
  • контролирует ускорение и замедление движения

FlyToInterpolator и его поведение

FlyToInterpolator реализует анимацию, имитирующую “полёт камеры” над поверхностью карты.

Он учитывает:

  • кривизну сферы Земли
  • изменение масштаба при приближении
  • плавную траекторию между точками

Математически движение делится на этапы:

  1. Интерполяция центра (longitude/latitude)
  2. Экспоненциальное изменение zoom
  3. Согласование угловых параметров (bearing/pitch)

Пример использования:

import {FlyToInterpolator} from '@deck.gl/core';

const nextViewState = {
  longitude: 2.3522,
  latitude: 48.8566,
  zoom: 11,
  bearing: 20,
  pitch: 45,
  transitionDuration: 3000,
  transitionInterpolator: new FlyToInterpolator()
};

Easing-функции и характер движения камеры

Функции сглаживания определяют поведение анимации во времени.

Наиболее распространённые формы:

  • linear: равномерное движение
  • easeIn: ускорение в начале
  • easeOut: замедление в конце
  • easeInOut: комбинация ускорения и замедления

Пример:

transitionEasing: t => t * t * (3 - 2 * t)

Эта функция создаёт плавное ускорение и торможение без резких скачков.


Программное управление анимацией viewport

Изменение viewState вручную позволяет создавать сложные сценарии навигации:

function moveToParis() {
  setViewState({
    longitude: 2.3522,
    latitude: 48.8566,
    zoom: 12,
    transitionDuration: 2500,
    transitionInterpolator: new FlyToInterpolator()
  });
}

Каждое новое состояние автоматически запускает анимацию, если задан transitionDuration.


Прерывание и переопределение анимации

Если во время анимации приходит новое viewState, текущий переход прерывается, и начинается новый.

Это создаёт модель:

state_n → transition → state_n+1 → transition → state_n+2

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


Интерактивная анимация и user-driven transitions

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

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

  • жесты пользователя создают мгновенные viewState
  • программные переходы могут продолжать или заменять движение
  • возможна конкуренция между drag-событиями и transition-анимацией

Interpolator как расширяемый механизм

Deck.gl позволяет создавать собственные интерполяторы, переопределяя логику перехода.

Структура интерполятора:

class CustomInterpolator {
  interpolateViewStates(from, to, t) {
    return {
      longitude: from.longitude + (to.longitude - from.longitude) * t,
      latitude: from.latitude + (to.latitude - from.latitude) * t,
      zoom: from.zoom + (to.zoom - from.zoom) * t
    };
  }
}

Это даёт полный контроль над траекторией камеры.


Анимация в многовидовых сценах

При использовании View-системы (например, MapView, OrthographicView, FirstPersonView) каждый viewport имеет собственное состояние.

Пример:

const views = [
  new MapView({id: 'map'}),
  new FirstPersonView({id: 'fp'})
];

Каждый view может иметь независимую анимацию viewState, но синхронизация возможна через общий state store.


Кинематическая модель движения камеры

Анимация viewport в Deck.gl можно описать как систему кинематики:

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

Обобщённая модель движения:

C(t) = C0 + (C1 - C0) * s(t)

где s(t) — функция сглаживания траектории.

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

Δangle = ((end - start + 180) % 360) - 180

что предотвращает “длинные” вращения.


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

Анимация выполняется на каждом кадре render loop, поэтому критичны:

  • минимизация пересоздания объектов interpolator
  • стабильность ссылок на viewState
  • отсутствие лишних React re-render

Deck.gl оптимизирует вычисления через WebGL pipeline, оставляя CPU только для расчёта состояния камеры.


Связь viewport-анимации с слоями

Изменение viewport влияет на:

  • пересчёт проекций координат
  • обновление видимости объектов
  • уровень детализации (LOD)
  • кластеризацию и фильтрацию данных

Каждый кадр анимации фактически является новым состоянием сцены, а не только перемещением камеры.