Canvas-рендерер: производительность и применение

Canvas-рендерер в Lottie Web представляет собой альтернативный способ отрисовки анимаций, при котором графическая сцена композируется не через DOM/SVG-элементы, а через 2D-контекст <canvas>. Это принципиально меняет модель производительности, структуру обновлений и характер потребления ресурсов.

Основная задача canvas-рендерера — максимально быстро преобразовывать векторную анимацию, экспортированную из After Effects через Bodymovin, в растровые кадры с минимальными затратами на управление DOM и перерисовку отдельных узлов сцены.


Архитектура рендеринга Canvas в Lottie

Внутренняя модель Lottie строится вокруг композиции (composition), слоёв (layers) и элементов (shapes). Canvas-рендерер переводит эту иерархию в последовательность команд CanvasRenderingContext2D.

Ключевые этапы кадра:

  • расчёт текущего состояния анимации (time-based evaluation)
  • применение трансформаций слоёв
  • построение путей (paths) для векторных форм
  • применение масок и маттов
  • растеризация и отрисовка на canvas

В отличие от SVG-рендерера, где каждый элемент существует как DOM-нода, canvas-версия работает в режиме immediate mode: каждый кадр полностью перерисовывается.


Модель кадра и жизненный цикл отрисовки

Каждый тик анимации инициирует пересборку сцены:

  1. Очистка холста (clearRect)
  2. Итерация по слоям композиции
  3. Вычисление матриц трансформации
  4. Построение путей через beginPath / moveTo / bezierCurveTo
  5. Применение заливки и обводки
  6. Восстановление состояния контекста через save / restore

Особенность модели заключается в том, что никакие элементы не сохраняются между кадрами. Это уменьшает накладные расходы на DOM, но увеличивает нагрузку на CPU при сложных сценах.


Производительность: сильные и слабые стороны canvas-рендерера

Canvas-рендерер демонстрирует предсказуемую производительность при большом количестве объектов благодаря отсутствию DOM-дерева.

Преимущества

  • Отсутствие затрат на layout/reflow/repaint DOM
  • Линейная зависимость стоимости кадра от количества draw calls
  • Более стабильный FPS при сложных интерфейсных сценах
  • Меньше накладных расходов на память по сравнению с большим SVG DOM

Ограничения

  • Полная перерисовка каждого кадра
  • Высокая стоимость сложных масок и маттов
  • Ограниченная интерактивность отдельных элементов
  • Рост CPU нагрузки при большом количестве path-операций

Векторные пути и их растеризация

Основная нагрузка canvas-рендерера связана с обработкой векторных контуров. Каждый shape преобразуется в последовательность команд Canvas API.

Типичный pipeline:

  • Shape Layer → Path2D (или ручная отрисовка)
  • Применение трансформаций через матрицы
  • Заполнение (fill) или обводка (stroke)

При сложных анимациях количество path-команд становится критическим фактором производительности.

Оптимизация часто сводится к сокращению числа сегментов кривых Безье и уменьшению количества отдельных shape-слоёв.


Маски и track matte: стоимость вычислений

Canvas-рендерер реализует маскирование через операции контекста:

  • globalCompositeOperation
  • offscreen clipping paths
  • временные canvas-буферы

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

Особенно затратны:

  • альфа-маски с мягкими границами
  • несколько уровней track matte
  • анимированные маски

Transform stack и матричные вычисления

Каждый слой в Lottie имеет собственную матрицу трансформации:

  • translate
  • scale
  • rotation
  • anchor point смещение

Canvas-рендерер применяет их через:

  • context.setTransform
  • или стек save/restore с последовательными transform

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

Оптимизация в этом контексте заключается в:

  • мемоизации матриц
  • пропуске неизменённых слоёв
  • минимизации глубины иерархии трансформаций

Кэширование и оптимизация отрисовки

Lottie Canvas-рендерер может использовать кэширование отдельных элементов сцены:

  • prerender слоёв в offscreen canvas
  • кэш сложных shape-групп
  • хранение растровых представлений статичных элементов

Кэширование особенно эффективно для:

  • неподвижных фонов
  • повторяющихся элементов UI
  • сложных векторных логотипов

При этом стоимость кэша выражается в:

  • дополнительной памяти
  • задержке первичной отрисовки

Device Pixel Ratio и четкость изображения

Canvas-рендеринг зависит от плотности пикселей экрана. При высоких значениях devicePixelRatio происходит масштабирование буфера:

  • увеличение внутреннего разрешения canvas
  • масштабирование контекста через scale(dpr, dpr)

Без учёта DPR возникают артефакты:

  • размытые линии
  • потеря четкости текста
  • искажение тонких контуров

С ростом DPR линейно увеличивается стоимость fill/stroke операций.


Сравнение Canvas и SVG-рендерера в Lottie Web

Canvas и SVG-рендереры решают одну задачу разными подходами.

SVG:

  • сохраняет сцену как DOM
  • позволяет адресовать элементы
  • дороже при большом количестве узлов

Canvas:

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

При росте числа элементов canvas демонстрирует более стабильное время кадра, тогда как SVG начинает страдать от DOM-операций и пересчёта стилей.


Области применения Canvas-рендерера

Canvas-рендерер эффективен в сценариях, где приоритетом является стабильный FPS:

  • UI-анимации высокой плотности
  • full-screen motion graphics
  • анимации загрузки и переходов
  • фоновые визуальные эффекты
  • сложные композиции без необходимости интерактивности

Менее эффективен в случаях:

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

Управление нагрузкой и частотой кадров

Производительность Canvas-рендерера напрямую зависит от частоты вызова render loop.

Основные механизмы управления:

  • синхронизация с requestAnimationFrame
  • пропуск кадров при высокой нагрузке
  • ограничение FPS вручную
  • адаптация качества (quality scaling)

При перегрузке CPU возможна деградация до:

  • пропуска промежуточных кадров
  • уменьшения разрешения canvas
  • отключения части эффектов (blur, shadows)

Тени, blur и фильтры как фактор деградации

Canvas API накладывает значительные ограничения на производительность визуальных эффектов.

Наиболее затратные операции:

  • shadowBlur
  • shadowOffset
  • сложные filter цепочки
  • полупрозрачные многослойные композиции

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


Внутренние оптимизации Lottie Web Canvas

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

  • минимизация вызовов save/restore
  • батчинг path-операций
  • пропуск скрытых слоёв
  • проверка dirty-state слоёв
  • кеширование computed styles

Особое значение имеет система dirty flags: только изменённые части сцены пересчитываются, остальные повторно используют предыдущие вычисления.


Поток выполнения и синхронизация

Рендер canvas строго привязан к главному потоку JavaScript. Это создаёт ограничение:

  • любые тяжёлые вычисления блокируют отрисовку
  • отсутствует нативный параллелизм для draw calls
  • невозможность частичного рендеринга без дополнительных буферов

В некоторых архитектурах используется:

  • OffscreenCanvas
  • Web Workers для подготовки данных сцены
  • перенос вычислений кривых и трансформаций вне main thread