Lifecycle в контексте анимаций — это полный цикл существования
анимационного процесса: от инициализации до завершения или остановки. В
библиотеке Popmotion lifecycle контролируется через объекты анимаций и
механизмы подписки (start, stop,
complete), позволяя точно управлять поведением во
времени.
Каждая анимация в Popmotion представляет собой поток значений, который можно запускать, останавливать и отслеживать. Управление lifecycle критично при построении сложных интерфейсов, где требуется синхронизация, отмена или повторный запуск анимаций.
startЛюбая анимация в Popmotion запускается с помощью метода
start. Он принимает обработчик, который вызывается при
каждом обновлении значения.
import { tween } from "popmotion";
const animation = tween({ from: 0, to: 100, duration: 1000 });
const controls = animation.start({
update: v => console.log(v),
complete: () => console.log("Завершено")
});
Ключевые особенности:
update вызывается на каждом кадреcomplete вызывается при завершении анимацииstart возвращает объект управления
(controls)Результат вызова start — это объект, который позволяет
контролировать lifecycle:
controls.stop();
Основные методы:
stop() — принудительная остановка анимацииОстановка анимации не вызывает complete, что важно
учитывать при построении логики.
completeАнимация считается завершённой, если она достигла своего конечного состояния без прерывания.
tween({ from: 0, to: 1 })
.start({
update: v => {},
complete: () => console.log("Анимация завершена")
});
Особенности:
stop()Прерывание — это остановка анимации до её завершения:
const controls = tween({ from: 0, to: 100 }).start({
update: v => console.log(v)
});
setTimeout(() => {
controls.stop();
}, 500);
Поведение:
complete не вызываетсяЭто особенно важно при смене состояний интерфейса, когда старая анимация больше не актуальна.
После остановки анимации её необходимо запускать заново:
const animation = tween({ from: 0, to: 100 });
let controls = animation.start({ update: v => console.log(v) });
// позже
controls.stop();
// новый запуск
controls = animation.start({ update: v => console.log(v) });
Каждый вызов start создаёт новый lifecycle.
Часто требуется координировать несколько анимаций. Для этого удобно хранить ссылки на их контроллеры:
const animations = [];
animations.push(
tween({ from: 0, to: 100 }).start({ update: v => console.log(v) })
);
animations.push(
tween({ from: 100, to: 0 }).start({ update: v => console.log(v) })
);
// остановка всех
animations.forEach(a => a.stop());
Popmotion предоставляет инструменты для объединения анимаций:
parallelimport { parallel, tween } from "popmotion";
parallel(
tween({ from: 0, to: 100 }),
tween({ from: 1, to: 0 })
).start({
update: ([x, y]) => console.log(x, y),
complete: () => console.log("Все завершены")
});
Lifecycle завершается, когда завершены все вложенные анимации.
chainimport { chain, tween } from "popmotion";
chain(
tween({ from: 0, to: 100 }),
tween({ from: 100, to: 200 })
).start({
update: v => console.log(v),
complete: () => console.log("Цепочка завершена")
});
Каждая следующая анимация запускается после завершения предыдущей.
valueДля более тонкого контроля lifecycle используется
value:
import { value, tween } from "popmotion";
const val = value(0, v => console.log(v));
const controls = tween({ to: 100 }).start(val);
Преимущества:
При работе с value можно управлять подписками:
const subscription = val.subscribe(v => console.log("Sub:", v));
// позже
subscription.unsubscribe();
Это позволяет контролировать lifecycle подписчиков отдельно от самой анимации.
Popmotion поддерживает реактивный подход, где анимации можно комбинировать:
import { tween } from "popmotion";
const animation = tween({ from: 0, to: 100 });
const controls = animation.start({
update: v => console.log(v)
});
// управление жизненным циклом
setTimeout(() => controls.stop(), 300);
В Popmotion нет встроенного метода pause, но его можно
реализовать:
let current = 0;
let controls;
function startAnimation(from) {
controls = tween({ from, to: 100, duration: 1000 })
.start({
update: v => current = v
});
}
startAnimation(0);
// пауза
setTimeout(() => {
controls.stop();
}, 500);
// продолжение
setTimeout(() => {
startAnimation(current);
}, 1000);
Важно освобождать ресурсы при завершении работы:
stop)unsubscribe)Это предотвращает утечки памяти и лишние вычисления.
1. Отсутствие остановки Анимации продолжают работать даже когда компонент уничтожен.
2. Дублирование запусков Несколько
start без остановки предыдущих анимаций.
3. Игнорирование complete Пропуск
логики завершения цепочек.
4. Потеря ссылок на controls Невозможность остановить анимацию позже.
let controls;
function open() {
if (controls) controls.stop();
controls = tween({ from: 0, to: 1 }).start({
update: v => {
document.body.style.opacity = v;
}
});
}
function close() {
if (controls) controls.stop();
controls = tween({ from: 1, to: 0 }).start({
update: v => {
document.body.style.opacity = v;
}
});
}
Здесь lifecycle каждой анимации контролируется явно, предотвращая конфликты.
Централизованный менеджер анимаций
Инкапсуляция lifecycle
Декларативный подход
При построении сложных систем lifecycle становится частью архитектуры:
Popmotion предоставляет низкоуровневые инструменты, позволяя гибко выстраивать lifecycle под конкретные задачи.