Библиотека Lottie Web позволяет привязывать JSON-анимации к состояниям интерфейсных элементов, превращая статические кнопки и иконки в управляемые анимированные компоненты без необходимости ручной работы с Canvas или SVG-анимацией.
Интерактивные элементы интерфейса строятся на базе сочетания событий
DOM и управления проигрыванием Lottie-анимаций через API
lottie-web. Основная концепция заключается в разделении
анимации на логические состояния: ожидание, наведение, нажатие, активное
состояние и отключённое состояние. Каждое состояние сопоставляется с
определённым сегментом или временным диапазоном внутри
JSON-анимации.
Подключение библиотеки выполняется через импорт:
import lottie from "lottie-web";
Создание базового контейнера для кнопки подразумевает наличие DOM-элемента, в который будет внедрена анимация:
<div class="lottie-button" id="saveButton"></div>
Инициализация анимации связывает JSON-файл с контейнером:
const buttonAnimation = lottie.loadAnimation({
container: document.getElementById("saveButton"),
renderer: "svg",
loop: false,
autoplay: false,
path: "/animations/save-button.json"
});
Использование renderer: "svg" обеспечивает
масштабируемость интерфейсного элемента без потери качества, что
критично для адаптивных интерфейсов.
Анимации для кнопок проектируются так, чтобы содержать несколько логических сегментов. Каждый сегмент соответствует определённому состоянию интерфейса.
Пример разбиения временной шкалы:
Управление сегментами осуществляется через API:
buttonAnimation.playSegments([15, 40], true);
Второй параметр true принудительно сбрасывает текущую
анимацию и запускает указанный диапазон.
Связь между DOM-событиями и Lottie-анимацией реализуется через стандартные обработчики событий браузера.
const button = document.getElementById("saveButton");
button.addEventListener("mouseenter", () => {
buttonAnimation.playSegments([15, 40], true);
});
button.addEventListener("mousedown", () => {
buttonAnimation.playSegments([40, 70], true);
});
button.addEventListener("mouseup", () => {
buttonAnimation.playSegments([70, 100], true);
});
button.addEventListener("mouseleave", () => {
buttonAnimation.playSegments([0, 15], true);
});
Такая модель позволяет создавать поведение, аналогичное нативным компонентам UI-фреймворков, но с визуальной гибкостью анимаций.
При использовании сложных интерфейсов состояния кнопок часто зависят не только от пользовательских событий, но и от бизнес-логики приложения.
Для этого вводится слой абстракции:
const ButtonState = {
IDLE: "idle",
HOVER: "hover",
ACTIVE: "active",
LOADING: "loading",
DISABLED: "disabled"
};
function setButtonState(state) {
switch (state) {
case ButtonState.IDLE:
buttonAnimation.playSegments([0, 15], true);
break;
case ButtonState.HOVER:
buttonAnimation.playSegments([15, 40], true);
break;
case ButtonState.ACTIVE:
buttonAnimation.playSegments([40, 70], true);
break;
case ButtonState.LOADING:
buttonAnimation.loop = true;
buttonAnimation.playSegments([70, 90], true);
break;
case ButtonState.DISABLED:
buttonAnimation.stop();
buttonAnimation.goToAndStop(0, true);
break;
}
}
Такой подход позволяет синхронизировать визуальное поведение с логикой приложения без привязки к DOM-событиям.
Lottie Web поддерживает тонкое управление проигрыванием, включая переходы между кадрами и зацикливание отдельных сегментов.
Для индикаторов загрузки используется непрерывное воспроизведение:
buttonAnimation.loop = true;
buttonAnimation.playSegments([90, 120], true);
При необходимости точного контроля применяется метод
goToAndPlay:
buttonAnimation.goToAndPlay(45, true);
Это позволяет запускать анимацию с конкретного кадра, что важно для синхронизации с внешними событиями, например ответами API.
При массовом использовании Lottie-анимаций в интерфейсе возникает нагрузка на DOM и графический слой. Основные подходы к оптимизации включают:
autoplay: false для предотвращения
лишнего рендераПример предзагрузки:
const preloaded = lottie.loadAnimation({
container: document.createElement("div"),
renderer: "svg",
loop: false,
autoplay: false,
path: "/animations/icon.json"
});
preloaded.stop();
SVG-рендеринг предпочтителен для интерфейсов с низкой и средней сложностью, тогда как Canvas может использоваться при высокой плотности анимационных элементов.
Lottie-анимации часто комбинируются с CSS для управления геометрией и позиционированием элементов, оставляя визуальную динамику исключительно на стороне JSON-анимации.
.lottie-button {
width: 48px;
height: 48px;
cursor: pointer;
display: inline-block;
}
CSS не управляет внутренним состоянием анимации, но определяет область взаимодействия и поведение курсора, что позволяет отделить визуальную логику от логики взаимодействия.
При создании интерфейсов с повторяющимися элементами, такими как списки или панели инструментов, каждый элемент получает собственный экземпляр Lottie.
document.querySelectorAll(".lottie-button").forEach((el) => {
lottie.loadAnimation({
container: el,
renderer: "svg",
loop: false,
autoplay: false,
path: "/animations/button.json"
});
});
При таком подходе важно избегать синхронного запуска всех анимаций одновременно, чтобы не перегружать основной поток рендеринга.
Анимационные кнопки часто зависят от асинхронных процессов, таких как запросы к серверу. В этом случае состояние “loading” удерживается до завершения операции.
setButtonState(ButtonState.LOADING);
fetch("/api/save", { method: "POST" })
.then(() => setButtonState(ButtonState.ACTIVE))
.catch(() => setButtonState(ButtonState.IDLE));
Анимация становится визуальным отражением состояния системы, а не только реакции на пользовательский ввод.
Lottie предоставляет события жизненного цикла, позволяющие синхронизировать интерфейсные переходы:
buttonAnimation.addEventListener("complete", () => {
setButtonState(ButtonState.IDLE);
});
Это используется для одноразовых анимаций подтверждения действий, таких как успешное сохранение или отправка формы.
Адаптивность обеспечивается за счёт SVG-масштабирования и динамического изменения контейнера:
buttonAnimation.setSpeed(1.2);
buttonAnimation.resize();
Размер анимации остаётся независимым от плотности пикселей, что упрощает интеграцию в responsive-интерфейсы без дополнительной переработки графики.
Полноценный компонент кнопки строится как комбинация трёх слоёв:
Такое разделение позволяет масштабировать интерфейс, не нарушая связность логики и визуального представления, а также упрощает повторное использование компонентов в разных частях приложения.