Transition для свойств слоев

В библиотеке Deck.gl система переходов свойств слоёв предназначена для плавной интерполяции между старым и новым состоянием визуализации при изменении входных параметров слоя. Это ключевой механизм для создания анимаций при обновлении данных без ручного управления кадрами и временными циклами.

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

Основная идея заключается в том, что при обновлении props слоя Deck.gl не заменяет значения мгновенно, а вычисляет промежуточные состояния на протяжении заданного времени.


Объявление переходов в слое

Механизм transitions активируется через свойство transitions, передаваемое в конфигурации слоя.

new ScatterplotLayer({
  id: 'points',
  data,
  getPosition: d => d.position,
  getRadius: d => d.radius,
  getFillColor: d => d.color,

  transitions: {
    getPosition: 1000,
    getRadius: 800,
    getFillColor: 1200
  }
});

Каждое свойство в объекте transitions определяет длительность анимации в миллисекундах для соответствующего accessor-поля.

Если новое значение приходит при обновлении слоя, Deck.gl автоматически интерполирует между предыдущим и новым состоянием.


Архитектура интерполяции значений

Внутри Deck.gl переходы реализуются как состояние между двумя версиями props:

  • previous props (старое состояние)
  • next props (новое состояние)
  • progress t ∈ [0, 1]

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

value(t) = interpolate(oldValue, newValue, easing(t))

Интерполяция зависит от типа данных:

  • скаляры: линейная интерполяция
  • векторы (позиции): покомпонентная интерполяция
  • цвета: интерполяция по RGBA каналам
  • углы: с нормализацией диапазона

Типы поддерживаемых свойств

Геометрические свойства

Наиболее часто анимируются координаты:

  • getPosition
  • getSourcePosition / getTargetPosition (в линейных слоях)
  • getElevation

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


Визуальные свойства

К ним относятся параметры внешнего вида:

  • getFillColor
  • getLineColor
  • getRadius
  • getWidth
  • opacity

Эти свойства позволяют создавать эффекты плавного изменения визуального состояния без пересоздания слоя.


Структурные свойства

Некоторые слои поддерживают более сложные параметры:

  • массивы координат (например, PathLayer)
  • геометрические формы (PolygonLayer)
  • атрибуты вершин

В этих случаях интерполяция выполняется поэлементно внутри структуры данных.


Обновление данных и запуск перехода

Переход запускается при изменении props слоя. Важное условие: Deck.gl сравнивает новое значение с предыдущим.

layer = new ScatterplotLayer({
  id: 'points',
  data: newData,
  getPosition: d => d.position,
  transitions: {
    getPosition: 1000
  }
});

При каждом обновлении:

  1. фиксируется текущее состояние атрибутов
  2. принимается новое состояние
  3. запускается таймер анимации
  4. происходит пофреймовая интерполяция

Easing-функции

По умолчанию используется линейная интерполяция, но Deck.gl поддерживает кастомные easing-функции.

transitions: {
  getPosition: {
    duration: 1200,
    easing: t => t * t * (3 - 2 * t)
  }
}

Easing влияет на скорость изменения параметров во времени:

  • ease-in: медленный старт, ускорение
  • ease-out: быстрое начало, замедление
  • ease-in-out: комбинированный режим

Объектная конфигурация переходов

Помимо числового значения длительности, допускается расширенная конфигурация:

transitions: {
  getPosition: {
    duration: 1000,
    easing: t => t,
    enter: 0,
    onStart: () => {},
    onEnd: () => {}
  }
}

Параметры:

  • duration — длительность анимации
  • easing — функция интерполяции
  • enter — начальное значение прогресса для новых элементов
  • onStart — вызывается при старте перехода
  • onEnd — вызывается после завершения

Переходы при изменении набора данных

Особое поведение наблюдается при динамическом изменении массива data.

Добавление элементов

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

transitions: {
  getPosition: {
    duration: 700,
    enter: 0
  }
}

Новые элементы могут появляться из:

  • нулевого радиуса
  • прозрачности 0
  • стартовой позиции

Удаление элементов

Удалённые элементы не исчезают мгновенно. Вместо этого они переходят в состояние выхода, если слой поддерживает это поведение.

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


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

Переходы напрямую связаны с обновлением GPU-атрибутов. Основная нагрузка распределяется следующим образом:

  • CPU: расчёт промежуточных значений
  • GPU: отрисовка кадров
  • память: хранение старых и новых атрибутов

Оптимизации:

  • минимизация числа анимируемых свойств
  • избегание сложных easing-функций
  • группировка обновлений data

При большом количестве объектов предпочтительно ограничивать число одновременно анимируемых атрибутов.


Взаимодействие с updateTriggers

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

getPosition: d => d.position,
updateTriggers: {
  getPosition: dataVersion
}

Если updateTriggers изменяется, происходит пересчёт атрибутов, после чего может быть запущен переход.

Важно различать:

  • updateTriggers → пересчёт данных
  • transitions → анимация между состояниями

Конфликты обновлений и прерывание анимации

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

Поведение:

  • новое значение перезапускает анимацию
  • текущее состояние становится исходной точкой
  • предыдущая анимация теряется

Это важно при потоковых данных, где обновления приходят с высокой частотой.


Интерполяция сложных структур

Для многокомпонентных атрибутов применяется рекурсивная интерполяция:

Цвет

rgba1 → rgba2

Каждый канал интерполируется отдельно.

Геометрия

Для линий и полигонов:

  • интерполяция вершин
  • выравнивание длины массивов
  • обработка отсутствующих точек

Если структуры несовместимы, Deck.gl может пропускать анимацию или применять мгновенное переключение.


Связь с шейдерами

Промежуточные значения передаются в GPU через attribute buffers. В вершинных шейдерах используется уже интерполированное состояние.

Это означает:

  • JS отвечает за генерацию значений
  • WebGL отвечает за отрисовку

Разделение позволяет поддерживать высокую частоту кадров даже при сложных сценах.


Типичные паттерны использования

Морфинг кластеров

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

Анимация потоков

Изменение getWidth и getColor для отображения интенсивности потоков.

Переключение режимов визуализации

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


Ограничения механизма

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

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


Синхронизация нескольких слоёв

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

transitions: {
  getPosition: 1000,
  getColor: 1000,
  getRadius: 1000
}

Это обеспечивает согласованное визуальное поведение всех слоёв сцены.