Lottie Web использует JSON-описание анимации, экспортированное из After Effects через Bodymovin. При работе с локальными файлами основная задача заключается в корректном получении JSON-структуры, её проверке и передаче в рендерер без промежуточных серверных запросов.
Работа с локальной загрузкой предполагает наличие минимальной разметки и контейнера для рендера анимации.
<div id="lottie-container"></div>
<input type="file" id="lottie-file" accept="application/json" />
Контейнер служит целью для отрисовки, а input обеспечивает доступ к файловой системе браузера в рамках ограничений безопасности.
Инициализация экземпляра Lottie осуществляется через метод
lottie.loadAnimation.
import lottie from "lottie-web";
const animationInstance = lottie.loadAnimation({
container: document.getElementById("lottie-container"),
renderer: "svg",
loop: true,
autoplay: false,
animationData: null
});
Параметр animationData в данном случае остаётся пустым
до момента загрузки локального файла.
Доступ к локальному файлу реализуется через FileReader.
Браузер предоставляет объект File, содержащий выбранный
JSON.
const input = document.getElementById("lottie-file");
input.addEventListener("change", (event) => {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onl oad = (e) => {
const text = e.target.result;
};
reader.readAsText(file);
});
Метод readAsText преобразует бинарное содержимое в
строку, пригодную для дальнейшего парсинга.
После получения текстового представления выполняется преобразование в объект.
let animationData;
try {
animationData = JSON.parse(text);
} catch (error) {
console.error("Некорректный JSON файл");
}
После успешного разбора структура передаётся в уже созданный экземпляр или используется для перезагрузки анимации.
animationInstance.destroy();
lottie.loadAnimation({
container: document.getElementById("lottie-container"),
renderer: "svg",
loop: true,
autoplay: true,
animationData
});
Использование destroy() предотвращает наложение старого
состояния на новый рендер.
Альтернативная схема подразумевает создание анимации только после загрузки файла.
let currentAnimation = null;
input.addEventListener("change", (event) => {
const file = event.target.files[0];
const reader = new FileReader();
reader.onl oad = (e) => {
const animationData = JSON.parse(e.target.result);
if (currentAnimation) {
currentAnimation.destroy();
}
currentAnimation = lottie.loadAnimation({
container: document.getElementById("lottie-container"),
renderer: "svg",
loop: true,
autoplay: true,
animationData
});
};
reader.readAsText(file);
});
Такой подход исключает необходимость хранения промежуточного состояния и упрощает управление жизненным циклом.
Файл Lottie содержит строго определённые поля: v,
fr, ip, op, layers,
assets. Отсутствие ключевых элементов приводит к
некорректному рендерингу.
Минимальная проверка может включать:
function isValidLottie(data) {
return (
data &&
typeof data === "object" &&
Array.isArray(data.layers) &&
typeof data.fr === "number"
);
}
Перед загрузкой выполняется проверка:
const animationData = JSON.parse(text);
if (!isValidLottie(animationData)) {
console.error("Структура не соответствует Lottie формату");
}
Внутри Lottie JSON часто содержится секция assets, где
указаны изображения или композиции.
При локальной загрузке возникает ограничение: пути к изображениям не всегда доступны напрямую через файловую систему браузера.
Типовая структура:
{
"assets": [
{
"id": "image_0",
"w": 200,
"h": 200,
"u": "images/",
"p": "img_0.png"
}
]
}
Поле u и p формируют путь к ресурсу. При
локальной загрузке корректная работа требует:
При использовании File API изображения также могут загружаться
отдельно через дополнительные input-элементы, с последующей подстановкой
в assets.
При частой смене файлов важна оптимизация перерисовки.
function updateAnimation(data) {
animationInstance.stop();
animationInstance.destroy();
animationInstance = lottie.loadAnimation({
container: document.getElementById("lottie-container"),
renderer: "svg",
loop: true,
autoplay: true,
animationData: data
});
}
SVG-рендерер в Lottie создаёт DOM-дерево, поэтому повторное использование контейнера без очистки приводит к накоплению элементов.
Помимо readAsText, используется
readAsArrayBuffer, что полезно для контроля над
кодировками.
reader.onl oad = (e) => {
const uint8Array = new Uint8Array(e.target.result);
const text = new TextDecoder("utf-8").decode(uint8Array);
const animationData = JSON.parse(text);
};
Такой подход обеспечивает более стабильную обработку больших файлов.
Ошибки могут возникать на нескольких уровнях:
reader.oner ror = () => {
console.error("Ошибка чтения файла");
};
try {
const data = JSON.parse(text);
} catch (e) {
console.error("Ошибка парсинга JSON");
}
Дополнительно проверяется версия:
if (data.v && parseFloat(data.v) > 5) {
console.warn("Версия Lottie может быть несовместима");
}
При работе с несколькими анимациями применяется массив файлов:
input.addEventListener("change", (event) => {
const files = Array.from(event.target.files);
files.forEach((file) => {
const reader = new FileReader();
reader.onl oad = (e) => {
const data = JSON.parse(e.target.result);
lottie.loadAnimation({
container: document.createElement("div"),
renderer: "svg",
loop: true,
autoplay: true,
animationData: data
});
};
reader.readAsText(file);
});
});
Каждый файл создаёт независимый экземпляр анимации, что требует контроля ресурсов при большом количестве загрузок.
Браузер может не триггерить change при выборе того же
файла повторно. Решение заключается в сбросе значения input:
input.value = "";
Сброс позволяет повторно инициировать событие выбора даже при идентичном файле.
При работе с крупными JSON-файлами применяются следующие принципы:
requestAnimationFrame для синхронизации
обновленийРендер SVG может создавать значительную нагрузку при сложных композициях, поэтому WebGL-рендерер иногда используется как альтернатива:
renderer: "canvas"
или
renderer: "svg"
При асинхронной загрузке важно разделять этапы:
Каждый этап может быть изолирован:
async function loadLottie(file) {
const text = await file.text();
const data = JSON.parse(text);
if (!isValidLottie(data)) return;
return lottie.loadAnimation({
container: document.getElementById("lottie-container"),
renderer: "svg",
loop: true,
autoplay: true,
animationData: data
});
}
Такой подход уменьшает связность логики и упрощает контроль ошибок на каждом этапе.