В формате 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 механизм разрешения путей опирается на несколько уровней:
assetsDir или path при
инициализации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.
При инициализации анимации может задаваться базовая директория ресурсов:
lottie.loadAnimation({
container: document.getElementById('anim'),
renderer: 'svg',
loop: true,
autoplay: true,
path: '/animations/anim.json',
assetsDir: '/animations/assets/'
});
assetsDir полностью переопределяет поведение
u внутри JSON. В этом случае поле u
игнорируется, а все ресурсы ищутся относительно указанного каталога.
Такая схема используется при:
В сложных системах часто требуется динамическое сопоставление ресурсов. Для этого используется постобработка 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.
При использовании сборщиков возникает проблема потери относительных путей. JSON может ссылаться на локальные файлы, которые при сборке перемещаются.
Типовой подход заключается в копировании ассетов в public директорию:
/public/lottie/animation.json
/public/lottie/images/...
И загрузке через абсолютный путь:
lottie.loadAnimation({
container: document.querySelector('#anim'),
renderer: 'svg',
path: '/lottie/animation.json'
});
В этом сценарии важно, чтобы структура директорий сохранялась полностью, так как Lottie Web не выполняет ре-резолвинг файлов через bundler.
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 и используется для:
При загрузке JSON через fetch или XHR критически важно понимать влияние origin:
uЕсли JSON загружен локально (file://), поведение путей
становится нестабильным, поскольку браузер не определяет базовый origin
корректно.
При размещении анимаций в 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");
}
Если путь не совпадает с реальным расположением, текстовые слои деградируют до системного шрифта.
Для унификации ресурсов часто применяется трансформация 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При ошибках загрузки Lottie Web не прерывает рендеринг, а заменяет ресурс пустым контейнером.
Система загрузки ресурсов следует фиксированному порядку:
imageProviderassetsDir, если заданu + p из JSONpНаличие более приоритетного уровня полностью перекрывает нижележащие механизмы.
При работе с динамическими CDN применяется токенизация URL:
function signUrl(path) {
return `${path}?token=${authToken}`;
}
И интеграция через imageProvider:
imageProvider: (asset, cb) => {
cb(signUrl(asset.u + asset.p));
}
Такой подход позволяет использовать защищённые хранилища без изменения структуры JSON.
SVG-рендерер использует DOM-элементы <image> и
<text>, где пути интерпретируются браузером
напрямую.
Canvas-рендерер, напротив, загружает изображения в память и кэширует их внутри WebGL/2D контекста. Это приводит к различиям:
Рациональная организация путей снижает нагрузку на сеть:
uИзбыточная глубина директорий увеличивает время резолвинга и усложняет кэширование.
При сложных системах доставки используется проверка доступности ресурсов до запуска анимации:
async function preloadAssets(assets) {
return Promise.all(
assets.map(a => fetch(a.u + a.p))
);
}
Это предотвращает частичный рендеринг и визуальные артефакты при задержках сети.