Motion One предоставляет механизм onUpdate как
центральную точку синхронизации с жизненным циклом анимации. Этот колбэк
вызывается на каждом кадре во время выполнения анимации и позволяет
получать актуальное состояние прогресса, времени и вычисленных значений
свойств без необходимости вручную подключаться к
requestAnimationFrame.
Внутренний цикл анимации в Motion One строится вокруг высокочастотного обновления состояния. На каждом кадре вычисляются:
onUpdate подключается после вычисления этих данных, но
до финального применения изменений к DOM, что делает его пригодным для
наблюдения и побочных эффектов.
Колбэк onUpdate передаётся в конфигурацию анимации через
animate:
import { animate } from "motion";
animate(
".box",
{ x: 300 },
{
onUpdate: (latest) => {
console.log(latest.x);
}
}
);
В данном контексте latest содержит текущее состояние
всех анимируемых свойств. Значения уже интерполированы с учётом easing и
времени.
latest, поступающий в onUpdate,
включает:
Пример структуры:
{
x: 120.5,
y: 0,
opacity: 0.7,
scale: 1.1
}
В сложных анимациях состав объекта зависит от набора анимируемых свойств и может расширяться динамически.
Помимо значений свойств, onUpdate часто применяется для
контроля прогресса:
animate(
".box",
{ x: 500 },
{
onUpdate: (latest) => {
const progress = latest.progress;
console.log(progress);
}
}
);
progress нормализован в диапазоне от 0 до
1 и отражает состояние выполнения анимации независимо от
длительности или easing.
onUpdate используется для синхронизации анимации с
внешними системами: canvas-рендерингом, аудио-параметрами или кастомными
визуальными эффектами.
animate(
".box",
{ rotate: 360 },
{
onUpdate: ({ rotate }) => {
drawSpinner(rotate);
}
}
);
Такая модель позволяет отделить вычисление анимации от рендеринга.
Внутренний поток данных в Motion One проходит несколько стадий:
onUpdateКлючевой момент заключается в том, что onUpdate получает
уже готовое промежуточное состояние, а не сырые входные параметры.
onUpdate вызывается многократно в процессе анимации,
тогда как onComplete срабатывает один раз после завершения
цикла.
animate(
".box",
{ x: 400 },
{
onUpdate: ({ x }) => {
console.log("frame:", x);
},
onComplete: () => {
console.log("finished");
}
}
);
Разделение этих двух механизмов позволяет отделять потоковые вычисления от финальных действий.
Частота вызова onUpdate соответствует частоте кадров
браузера, обычно 60 FPS. Это накладывает ограничения на выполняемые
внутри него операции.
Типичные ограничения:
Оптимальная модель — использование onUpdate как
источника данных, а не места для сложной логики.
При анимации нескольких свойств onUpdate получает
агрегированный объект:
animate(
".box",
{
x: 300,
y: 150,
opacity: 0.5
},
{
onUpdate: (latest) => {
const { x, y, opacity } = latest;
render(x, y, opacity);
}
}
);
Такой подход позволяет централизованно отслеживать изменения без раздельных подписок.
В timeline-режиме Motion One onUpdate получает значения,
зависящие от общей временной координаты всех анимаций.
import { timeline } from "motion";
timeline([
[".box", { x: 200 }, { duration: 1 }],
[".box", { y: 100 }, { duration: 1 }]
], {
onUpdate: (latest) => {
console.log(latest);
}
});
В этом случае объект состояния отражает комбинированный результат нескольких анимационных шагов.
onUpdate часто применяется как мост между императивной
анимацией и реактивной архитектурой:
animate(".box", { x: 1000 }, {
onUpdate: (latest) => {
store.setState({ position: latest.x });
}
});
В некоторых сценариях onUpdate может вызываться:
Motion One гарантирует согласованность состояния, поэтому даже при
прерывании анимации последний latest остаётся доступным в
рамках текущего кадра.
При создании сложных анимаций возможно наложение нескольких источников обновления. В таких случаях важно учитывать порядок выполнения:
onUpdate конкретной анимацииЭто позволяет строить многоуровневую систему реакций без конфликтов между слоями логики.