Изменение размеров Lottie-анимаций в runtime в Lottie Web строится вокруг взаимодействия контейнера, параметров рендера и внутренних механизмов пересчёта сцены. Библиотека Lottie Web не пересчитывает геометрию автоматически во всех сценариях, поэтому корректное масштабирование зависит от выбранного рендерера и способа привязки размеров к DOM.
Lottie-анимация привязывается к контейнеру, переданному в
loadAnimation. Размер сцены определяется не только
параметрами JSON, но и фактическими размерами DOM-элемента.
const animation = lottie.loadAnimation({
container: document.getElementById('anim'),
renderer: 'svg',
loop: true,
autoplay: true,
path: '/animation.json'
});
Контейнер становится базовой системой координат. При изменении его размеров библиотека должна быть уведомлена, иначе отрисовка останется в старом масштабе.
SVG масштабируется через viewBox. В большинстве случаев
изменение CSS-размеров контейнера приводит к автоматическому
масштабированию без перерасчёта кадров.
Ключевая особенность — зависимость от
preserveAspectRatio.
rendererSettings: {
preserveAspectRatio: 'xMidYMid meet'
}
Поведение:
meet — сохранение пропорций с возможными полямиslice — заполнение контейнера с обрезкойnone — растяжение без сохранения пропорцийSVG чаще всего не требует явного вызова пересчёта, но исключения возникают при динамическом изменении размеров родителя без изменения layout-событий.
Canvas требует явного пересчёта размеров. При изменении контейнера происходит изменение внутренних буферов отрисовки.
const animation = lottie.loadAnimation({
container: document.getElementById('anim'),
renderer: 'canvas',
path: '/animation.json'
});
При изменении размеров контейнера необходимо синхронизировать canvas:
animation.resize();
Без этого кадр остаётся в старом разрешении, что приводит к размытой или некорректной отрисовке.
HTML-рендерер использует DOM-элементы для каждого слоя.
Масштабирование зависит от CSS и трансформаций
transform: scale().
Особенность — высокая нагрузка при большом количестве слоёв и необходимость пересчёта позиционирования при resize.
Классический способ отслеживания изменений viewport:
window.addEventListener('resize', () => {
animation.resize();
});
Этот подход работает, но не учитывает изменения размеров контейнеров внутри сложных layout-систем.
Более точный механизм, реагирующий на изменение конкретного элемента:
const container = document.getElementById('anim');
const observer = new ResizeObserver(() => {
animation.resize();
});
observer.observe(container);
Использование ResizeObserver устраняет необходимость
реагировать на глобальные события окна.
При изменении размеров через анимации layout или drag-операции возникает частое срабатывание resize. Это приводит к лишним перерасчётам.
function debounce(fn, delay) {
let t;
return (...args) => {
clearTimeout(t);
t = setTimeout(() => fn(...args), delay);
};
}
const onRes ize = debounce(() => animation.resize(), 100);
window.addEventListener('resize', onResize);
resize() инициирует перерасчёт viewport и пересборку
матриц трансформации.
Внутренне происходит:
Частый вызов приводит к затратам CPU, особенно при сложных композициях.
Для canvas важно учитывать devicePixelRatio.
Без учёта DPR изображение становится размытым на дисплеях высокой плотности.
Типичная корректировка:
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const dpr = window.devicePixelRatio || 1;
canvas.width = container.clientWidth * dpr;
canvas.height = container.clientHeight * dpr;
ctx.scale(dpr, dpr);
В Lottie Web часть этой логики обрабатывается автоматически, но при кастомных интеграциях возможны расхождения.
Часто изменение размеров полностью делегируется CSS:
#anim {
width: 100%;
height: 100%;
}
При таком подходе Lottie зависит от layout-системы страницы.
Дополнительная стратегия:
#anim {
position: absolute;
inset: 0;
}
Это фиксирует контейнер в пределах родителя и упрощает масштабирование.
В сложных сценариях изменение размеров может сопровождаться пересборкой animation instance:
animation.destroy();
lottie.loadAnimation({
container,
renderer: 'svg',
path: '/animation.json'
});
Такой подход используется при смене:
Пересоздание дороже, чем resize, но обеспечивает
предсказуемость.
В SPA-фреймворках контейнер может быть не готов в момент инициализации.
Типичная проблема — нулевые размеры:
if (container.clientWidth === 0) {
requestAnimationFrame(init);
}
Также важен повторный вызов resize() после навигации
между страницами, так как DOM может быть повторно смонтирован с другими
размерами.
Распространённые ситуации:
Для стабильного поведения используется комбинация:
ResizeObserveranimation.resize()В современных layout-системах размеры контейнера часто изменяются без событий window.
Особенно в:
В этих случаях только ResizeObserver отражает
фактическое изменение геометрии.
Если контейнер получает display: none, размеры
становятся нулевыми. После повторного отображения требуется повторный
resize:
animation.resize();
Без этого возможны артефакты отрисовки или отсутствие кадров.
При высокой частоте изменений размеров применяется стратегия:
requestAnimationFramelet scheduled = false;
function scheduleResize() {
if (scheduled) return;
scheduled = true;
requestAnimationFrame(() => {
animation.resize();
scheduled = false;
});
}
На мобильных устройствах изменение orientation вызывает резкое изменение viewport.
window.addEventListener('orientationchange', () => {
setTimeout(() => animation.resize(), 200);
});
Задержка необходима для завершения перерасчёта layout браузером.
При использовании анимаций внутри модальных окон, сайдбаров и вкладок возникает необходимость повторного расчёта при каждом открытии.
Типичный сценарий:
resize() после открытияУстойчивые схемы работы с изменением размеров включают:
ResizeObserverresize()preserveAspectRatio