Инспектирование DOM-структуры

Lottie Web при рендеринге анимаций формирует в DOM сложную, но предсказуемую иерархию элементов, зависящую от выбранного режима отрисовки: svg, canvas или html. Понимание этой структуры критично для отладки, оптимизации производительности и интеграции анимаций в интерфейсы.


Базовая архитектура контейнера Lottie

После инициализации через lottie.loadAnimation в DOM появляется корневой контейнер, внутри которого библиотека строит собственное дерево элементов.

Типичная структура:

<div id="lottie">
  <svg ...>
    <defs>...</defs>
    <g>...</g>
  </svg>
</div>

или при canvas-рендеринге:

<div id="lottie">
  <canvas></canvas>
</div>

или при DOM-based рендеринге:

<div id="lottie">
  <div class="bm-root">
    <div class="bm-layer">...</div>
  </div>
</div>

Ключевой момент: структура не фиксирована на уровне HTML, она генерируется движком в зависимости от настроек.


Режим SVG: основная DOM-модель Lottie Web

SVG-режим является наиболее распространённым и инспектируемым вариантом.

Основные узлы

  • svg — корневой контейнер сцены
  • defs — определения градиентов, масок, клиппинга
  • g — группы слоёв
  • path — векторные формы
  • image — растровые элементы
  • text — текстовые слои

Пример типовой иерархии:

<svg>
  <defs>
    <clipPath id="cp_1">...</clipPath>
    <linearGradient id="gr_1">...</linearGradient>
  </defs>

  <g class="bm-layer" transform="matrix(...)">
    <g class="bm-shape">
      <path d="..." />
    </g>
  </g>
</svg>

Классы и соглашения именования

Lottie Web использует внутренние префиксы:

  • bm-layer — слой композиции
  • bm-shape — векторная форма
  • bm-fill — заливка
  • bm-stroke — обводка
  • bm-text — текстовый слой
  • bm-image — растровый слой

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


Связь DOM с JSON-структурой Lottie

Каждый DOM-узел соответствует объектам JSON:

{
  "layers": [
    {
      "ty": 4,
      "nm": "Shape Layer",
      "shapes": [...]
    }
  ]
}

Соответствие:

  • layers[]g.bm-layer
  • shapes[]g.bm-shape
  • ks (keyframes) → inline styles / transforms
  • c (color) → fill / stroke

DOM не является прямым отражением JSON, а представляет компиляцию структуры в SVG-дерево.


Inspecting transform-иерархии

Основной механизм анимации в Lottie Web основан на transform-атрибутах:

<g transform="matrix(1,0,0,1,120,80)">

или:

<g style="transform: translate3d(0px, 0px, 0px) scale(1);">

Типы трансформаций:

  • translation (позиция слоя)
  • scale (масштаб)
  • rotation (поворот)
  • skew (наклон, реже)

Каждый слой содержит собственную матрицу, вычисляемую движком на каждом кадре.


Ключевые DOM-узлы анимации

Векторные формы

Формируются через комбинацию:

<g class="bm-shape">
  <path d="M0 0 L100 0 L100 100 Z"></path>
</g>

Множественные формы группируются внутри одного слоя.


Заливки и обводки

<path class="bm-fill" fill="#ff0000"></path>
<path class="bm-stroke" stroke-width="2"></path>

Инспекция позволяет отслеживать динамическое изменение:

  • цвета
  • прозрачности
  • толщины линии

Текстовые слои

Текстовые элементы представлены через SVG <text> или набор <tspan>:

<text class="bm-text">
  <tspan x="0" y="0">Sample</tspan>
</text>

Особенность: текст может быть разбит на несколько сегментов для анимации отдельных символов.


Canvas-режим и отсутствие DOM-структуры

При использовании canvas-рендеринга DOM не содержит визуальных элементов сцены:

<div id="lottie">
  <canvas width="500" height="500"></canvas>
</div>

В этом режиме:

  • отсутствует доступ к внутренним слоям через DevTools
  • вся сцена отрисовывается в bitmap-буфере
  • инспектирование возможно только через API Lottie

HTML-режим и DOM-based рендеринг

HTML-рендеринг формирует структуру из div-элементов:

<div class="bm-layer">
  <div class="bm-shape">
    <div class="bm-fill"></div>
  </div>
</div>

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

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

Отладка через DevTools

Поиск слоёв

Использование селекторов:

document.querySelectorAll('.bm-layer')

или:

document.querySelector('svg')

Отслеживание изменений трансформаций

const layer = document.querySelector('.bm-layer');

const observer = new MutationObserver(() => {
  console.log(layer.getAttribute('transform'));
});

observer.observe(layer, { attributes: true });

Анализ производительности

Основные узкие места:

  • большое количество path
  • частые изменения transform
  • пересчёт layout в HTML-режиме

Внутренние группы и маскирование

Lottie активно использует SVG-механизмы:

ClipPath

<clipPath id="clip_1">
  <rect width="100" height="100"></rect>
</clipPath>

Маски

<g clip-path="url(#clip_1)">

Маски часто создают дополнительные группы g, увеличивая глубину DOM.


Иерархия вложенности слоёв

Типичная структура сложной композиции:

svg
 ├── defs
 ├── g (comp root)
 │    ├── g (layer 1)
 │    │    ├── g (shape group)
 │    │    ├── path
 │    ├── g (layer 2)
 │         ├── text
 │         ├── tspan

Глубина напрямую зависит от количества:

  • прекомпозиций
  • масок
  • выражений (expressions)
  • текстовых анимаций

Динамическая генерация DOM

Lottie Web не хранит статическую DOM-структуру. Вместо этого:

  • JSON парсится в дерево объектов
  • создаётся виртуальная модель слоёв
  • на каждом кадре обновляются только изменённые узлы
  • DOM синхронизируется через diff-подобный механизм

Особенности инспектирования в браузере

При работе с DevTools наблюдаются следующие эффекты:

  • элементы могут мигать при обновлении кадров
  • атрибуты transform меняются на каждом frame tick
  • некоторые узлы пересоздаются вместо обновления
  • SVG может содержать десятки тысяч узлов при сложных сценах

Практическая интерпретация DOM для анализа анимации

DOM-структура позволяет:

  • определить количество слоёв композиции
  • выявить перегруженные группы
  • найти источники repaint/reflow
  • локализовать маскирующие конструкции
  • анализировать трансформационные цепочки

Связь DOM и API экземпляра анимации

Через экземпляр:

const anim = lottie.loadAnimation({...});

доступны данные, которые косвенно отражаются в DOM:

  • anim.currentFrame
  • anim.totalFrames
  • anim.renderer

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