Обработка путей к ресурсам

В формате Lottie данные анимации представляют собой JSON-описание сцены, в котором ключевую роль играет блок assets. Именно он отвечает за внешние ресурсы: изображения, шрифты, дополнительные композиции. При рендеринге в Lottie Web обработка путей к этим ресурсам становится одной из ключевых задач, определяющих корректность отображения анимации.

Каждый ресурс внутри JSON содержит метаданные, включая идентификатор и путь:

{
  "id": "image_0",
  "w": 512,
  "h": 512,
  "u": "images/",
  "p": "img_0.png",
  "e": 0
}

Поля u и p формируют итоговый URL ресурса. Поле u отвечает за базовый путь, а p — за имя файла. В сумме они определяют местоположение изображения относительно JSON-файла.


Формирование итогового пути к изображениям

В Lottie Web механизм разрешения путей опирается на несколько уровней:

  1. Базовый путь, вычисляемый из URL JSON-файла
  2. Значение assetsDir или path при инициализации
  3. Переопределения через pathReplace или кастомные функции загрузки

Если JSON загружен с адреса:

https://cdn.example.com/animations/anim.json

и внутри указан ресурс:

"u": "images/",
"p": "frame_1.png"

итоговый путь формируется как:

https://cdn.example.com/animations/images/frame_1.png

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


Роль параметра assetsDir

При инициализации анимации может задаваться базовая директория ресурсов:

lottie.loadAnimation({
  container: document.getElementById('anim'),
  renderer: 'svg',
  loop: true,
  autoplay: true,
  path: '/animations/anim.json',
  assetsDir: '/animations/assets/'
});

assetsDir полностью переопределяет поведение u внутри JSON. В этом случае поле u игнорируется, а все ресурсы ищутся относительно указанного каталога.

Такая схема используется при:

  • раздельной публикации JSON и медиафайлов
  • CDN-распределении
  • сборке через bundler с переносом ассетов

Переопределение путей через assetMap

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

const animationData = response;

animationData.assets = animationData.assets.map(asset => {
  if (asset.p) {
    asset.p = `https://cdn.example.com/lottie/${asset.p}`;
  }
  return asset;
});

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


Обработка путей в Webpack и Vite окружении

При использовании сборщиков возникает проблема потери относительных путей. JSON может ссылаться на локальные файлы, которые при сборке перемещаются.

Типовой подход заключается в копировании ассетов в public директорию:

/public/lottie/animation.json
/public/lottie/images/...

И загрузке через абсолютный путь:

lottie.loadAnimation({
  container: document.querySelector('#anim'),
  renderer: 'svg',
  path: '/lottie/animation.json'
});

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


Кастомная загрузка изображений через imageProvider

SVG-рендерер позволяет перехватывать загрузку изображений:

lottie.loadAnimation({
  container: document.getElementById('anim'),
  renderer: 'svg',
  animationData,
  rendererSettings: {
    imagePreserveAspectRatio: 'xMidYMid slice',
    imageProvider: function (imageData, callback) {
      const url = `https://cdn.example.com/assets/${imageData.u}${imageData.p}`;
      callback(url);
    }
  }
});

Механизм imageProvider полностью заменяет стандартное поведение формирования URL и используется для:

  • авторизации через signed URLs
  • подмены CDN
  • lazy-loading изображений
  • оптимизации форматов (webp вместо png)

Работа с base URL и origin

При загрузке JSON через fetch или XHR критически важно понимать влияние origin:

  • относительные пути интерпретируются относительно JSON URL
  • абсолютные URL игнорируют u
  • протокол должен совпадать при отсутствии CORS-разрешений

Если JSON загружен локально (file://), поведение путей становится нестабильным, поскольку браузер не определяет базовый origin корректно.


CDN и стратегия хранения ресурсов

При размещении анимаций в CDN используется строгая структура:

/cdn/lottie/{animation_name}/animation.json
/cdn/lottie/{animation_name}/images/...

JSON сохраняет относительные пути, что позволяет переносить весь каталог без изменений.

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


Обработка шрифтов и их пути

В Lottie JSON шрифты описываются отдельно:

"fonts": {
  "list": [
    {
      "fFamily": "Roboto",
      "fPath": "fonts/roboto.ttf"
    }
  ]
}

При рендеринге SVG используется загрузка через @font-face:

@font-face {
  font-family: "Roboto";
  src: url("/fonts/roboto.ttf") format("truetype");
}

Если путь не совпадает с реальным расположением, текстовые слои деградируют до системного шрифта.


Модификация путей через post-process JSON

Для унификации ресурсов часто применяется трансформация JSON до передачи в Lottie Web:

function normalizePaths(data, baseUrl) {
  data.assets.forEach(asset => {
    if (asset.p && asset.u) {
      asset.p = `${baseUrl}/${asset.u}${asset.p}`;
      asset.u = '';
    }
  });
  return data;
}

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


Кэширование и влияние путей на повторное использование ресурсов

Браузерное кэширование зависит от конечного URL. Даже минимальное изменение пути приводит к повторной загрузке ресурса:

/images/frame_1.png?v=1
/images/frame_1.png?v=2

В Lottie Web это часто используется для принудительного обновления анимаций без изменения JSON.


Ошибки разрешения путей

Типовые проблемы возникают в следующих случаях:

  • отсутствие директории u в JSON
  • несоответствие регистра файлов на сервере
  • некорректные относительные пути при сборке
  • блокировка CORS при загрузке изображений
  • смешение HTTP и HTTPS

При ошибках загрузки Lottie Web не прерывает рендеринг, а заменяет ресурс пустым контейнером.


Приоритеты разрешения ресурсов

Система загрузки ресурсов следует фиксированному порядку:

  1. Кастомный imageProvider
  2. assetsDir, если задан
  3. u + p из JSON
  4. Абсолютный путь p

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


Интеграция с динамическими CDN

При работе с динамическими CDN применяется токенизация URL:

function signUrl(path) {
  return `${path}?token=${authToken}`;
}

И интеграция через imageProvider:

imageProvider: (asset, cb) => {
  cb(signUrl(asset.u + asset.p));
}

Такой подход позволяет использовать защищённые хранилища без изменения структуры JSON.


Особенности обработки путей в SVG и Canvas рендерах

SVG-рендерер использует DOM-элементы <image> и <text>, где пути интерпретируются браузером напрямую.

Canvas-рендерер, напротив, загружает изображения в память и кэширует их внутри WebGL/2D контекста. Это приводит к различиям:

  • SVG чувствителен к CORS
  • Canvas требует предварительной загрузки ресурсов
  • повторное использование изображений более эффективно в Canvas

Оптимизация структуры ресурсов

Рациональная организация путей снижает нагрузку на сеть:

  • группировка ассетов по анимациям
  • использование единых CDN-префиксов
  • минимизация вложенности u
  • унификация форматов изображений

Избыточная глубина директорий увеличивает время резолвинга и усложняет кэширование.


Контроль целостности ресурсов

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

async function preloadAssets(assets) {
  return Promise.all(
    assets.map(a => fetch(a.u + a.p))
  );
}

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