Lottie Web реализует воспроизведение анимаций через абстракцию рендереров. Анимация описывается единой JSON-моделью, а конечное отображение формируется одним из доступных движков визуализации. Архитектура построена так, что ядро интерпретирует таймлайн, слои и свойства, а рендерер отвечает за превращение этого состояния в графику.
Разделение на рендереры позволяет использовать разные графические API без изменения логики анимации. Основные реализации ориентированы на разные сценарии производительности, совместимости и качества отображения.
SVG является наиболее часто используемым вариантом. Он строит DOM-дерево из SVG-элементов и управляет их атрибутами во время проигрывания анимации.
Особенности SVG:
SVG подходит для интерфейсной анимации, иконок и умеренно сложных сцен.
Canvas-рендерер использует 2D контекст HTML5 Canvas. В отличие от SVG, он не создает DOM-структуру и рисует пиксели напрямую.
Особенности Canvas:
Canvas применяется в случаях сложной анимации, игровых интерфейсов и сцен с большим числом элементов.
HTML-рендерер преобразует слои в HTML-элементы и использует CSS-трансформации.
Особенности HTML:
HTML-рендерер используется реже и обычно в специфических интерфейсных сценариях.
Рендерер задается при создании экземпляра анимации через параметр
renderer.
lottie.loadAnimation({
container: document.getElementById('anim'),
renderer: 'svg',
loop: true,
autoplay: true,
path: 'animation.json'
});
Возможные значения:
"svg""canvas""html"Выбор определяется балансом между качеством визуализации и производительностью.
Прямое переключение рендерера у уже созданного экземпляра не поддерживается. Внутренняя архитектура Lottie Web не предусматривает динамическую замену графического движка без пересоздания всей сцены.
Стандартный механизм переключения реализуется через уничтожение текущего экземпляра и создание нового.
let animation;
function createAnimation(rendererType) {
animation = lottie.loadAnimation({
container: document.getElementById('anim'),
renderer: rendererType,
loop: true,
autoplay: true,
path: 'animation.json'
});
}
function switchRenderer(newRenderer) {
if (animation) {
animation.destroy();
}
createAnimation(newRenderer);
}
createAnimation('svg');
При смене рендерера происходит полная реконструкция графического слоя:
Состояние воспроизведения может быть сохранено вручную:
const currentFrame = animation.currentFrame;
animation.destroy();
animation = lottie.loadAnimation({
container: document.getElementById('anim'),
renderer: 'canvas',
loop: true,
autoplay: true,
path: 'animation.json'
});
animation.addEventListener('DOMLoaded', () => {
animation.goToAndStop(currentFrame, true);
});
При работе с несколькими типами устройств или режимами отображения применяется фабричный подход.
function getRendererByEnvironment() {
const isLowPowerDevice = navigator.hardwareConcurrency < 4;
const isMobile = /Mobi|Android/i.test(navigator.userAgent);
if (isLowPowerDevice || isMobile) {
return 'canvas';
}
return 'svg';
}
const animation = lottie.loadAnimation({
container: document.getElementById('anim'),
renderer: getRendererByEnvironment(),
loop: true,
autoplay: true,
path: 'animation.json'
});
SVG демонстрирует деградацию производительности при:
Canvas сохраняет стабильный FPS при:
HTML рендерер чувствителен к:
При необходимости переключения рендерера в интерактивных приложениях используется промежуточное сохранение состояния:
function snapshotState(anim) {
return {
frame: anim.currentFrame,
direction: anim.playDirection
};
}
function restoreState(anim, state) {
anim.goToAndStop(state.frame, true);
if (state.direction === -1) {
anim.setDirection(-1);
}
}
Комбинация сохранения состояния и пересоздания позволяет имитировать непрерывное переключение.
Практическая стратегия выбора рендерера может основываться на измерении производительности:
let fpsSamples = [];
function measureFPS(callback) {
let last = performance.now();
function frame() {
const now = performance.now();
fpsSamples.push(1000 / (now - last));
last = now;
if (fpsSamples.length < 30) {
requestAnimationFrame(frame);
} else {
const avg = fpsSamples.reduce((a, b) => a + b) / fpsSamples.length;
callback(avg);
}
}
requestAnimationFrame(frame);
}
measureFPS((fps) => {
const renderer = fps < 40 ? 'canvas' : 'svg';
lottie.loadAnimation({
container: document.getElementById('anim'),
renderer,
loop: true,
autoplay: true,
path: 'animation.json'
});
});
Каждая новая инициализация создаёт независимый экземпляр:
destroyВажно учитывать отсутствие внутреннего кеширования рендерера между инстансами.
Эти различия могут приводить к визуальным расхождениям одной и той же анимации при смене рендерера.
В системах с динамическим UI часто применяется комбинированная стратегия:
Управление осуществляется через централизованный менеджер анимаций, который пересоздает экземпляры при смене контекста отображения.