onComplete — callback-функция, вызываемая в момент полного завершения анимации в Motion One. Она срабатывает только один раз за жизненный цикл конкретной анимации и предназначена для выполнения финальных действий: очистки состояния, запуска следующей анимации, фиксации результата или синхронизации с внешней логикой приложения.
В Motion One завершением анимации считается достижение конечного
ключевого кадра с учётом всех параметров: длительности, задержек,
повторов и easing-функций. Callback onComplete вызывается
строго после того, как:
Ключевая особенность заключается в том, что onComplete
не срабатывает при каждом обновлении состояния, а только в финальной
точке жизненного цикла анимации.
В Motion One onComplete передаётся как часть объекта
опций при создании анимации:
animate(
element,
{ opacity: 1, transform: "translateY(0px)" },
{
duration: 0.6,
easing: "ease-out",
onComplete: () => {
// финальная логика
}
}
)
Callback не принимает аргументов в базовом варианте использования, но может быть связан с контекстом анимации через замыкания или внешние состояния.
Чтобы понять место onComplete, важно рассмотреть
упрощённый жизненный цикл:
onCompleteonComplete находится строго между завершением
интерполяции и освобождением внутренних ресурсов анимации. Это делает
его последней точкой синхронного вмешательства в процесс.
При стандартном течении анимации callback вызывается единожды:
animate(box, { x: 300 }, {
duration: 1,
onComplete: () => {
console.log("Анимация завершена")
}
})
В этом случае onComplete срабатывает после прохождения
всех кадров.
При использовании повторов важно учитывать, что
onComplete вызывается только после полного завершения всех
циклов:
animate(box, { rotate: 360 }, {
duration: 1,
repeat: 2,
onComplete: () => {
console.log("Все повторы завершены")
}
})
Если анимация повторяется 2 раза, callback сработает только после третьего финального прохода.
При repeat: Infinity onComplete не
вызывается никогда, так как финального состояния не существует.
При остановке анимации через API (stop,
cancel, изменение target-свойств) onComplete
не вызывается. Это важное отличие от некоторых других анимационных
систем, где существует отдельный callback отмены.
Motion One поддерживает Promise-совместимое завершение анимаций.
onComplete часто используется как аналог
.then() в цепочках:
animate(box, { x: 200 }, { duration: 0.5 })
.finished
.then(() => {
console.log("Завершено через Promise")
})
Однако onComplete выполняется независимо от
Promise-механизма и не заменяет его. Различие заключается в том,
что:
onComplete — синхронный callback.finished — Promise, который резолвится после
завершенияonComplete выполняется синхронно в момент завершения
анимации. Это означает, что:
Пример цепочки:
animate(a, { opacity: 0 }, {
onComplete: () => {
animate(b, { opacity: 1 })
}
})
В этом случае вторая анимация запускается сразу после завершения первой без задержек между кадрами.
onComplete часто используется как точка синхронизации
интерфейса:
Пример:
animate(modal, { opacity: 0, scale: 0.9 }, {
duration: 0.3,
onComplete: () => {
modal.style.display = "none"
}
})
Здесь важно, что DOM-стили изменяются только после завершения визуального перехода, что предотвращает резкие скачки интерфейса.
При использовании ключевых кадров onComplete вызывается
только после завершения всей последовательности:
animate(element, {
x: [0, 100, 50, 0]
}, {
duration: 2,
onComplete: () => {
console.log("Все keyframes завершены")
}
})
Callback не вызывается между промежуточными ключевыми точками, даже если они визуально выглядят как завершённые этапы.
При анимации свойств, влияющих на layout (например,
height, width, top),
onComplete гарантирует, что:
Это делает callback надёжной точкой для чтения DOM-метрик:
animate(box, { height: 300 }, {
onComplete: () => {
const finalHeight = box.getBoundingClientRect().height
}
})
Ошибка возникает при попытке использовать промежуточные состояния
вместо onComplete:
animate(box, { x: 200 })
console.log("готово") // неверно
Правильный вариант:
animate(box, { x: 200 }, {
onComplete: () => {
console.log("готово")
}
})
onComplete не вызывается при отмене анимации, поэтому
логика, завязанная на обязательное выполнение callback, может быть
нарушена при динамическом управлении UI.
onComplete не предназначен для отслеживания прогресса.
Он не вызывается во время анимации и не подходит для:
Для этих задач используется onUpdate.
При параллельных анимациях onComplete вызывается
отдельно для каждой:
animate(a, { x: 100 }, { onComplete: () => console.log("A done") })
animate(b, { y: 100 }, { onComplete: () => console.log("B done") })
Порядок вызовов зависит от длительности каждой анимации и не гарантируется относительно друг друга.
onComplete часто используется как базовый механизм
построения последовательностей без внешних библиотек:
animate(a, { x: 100 }, {
onComplete: () => {
animate(a, { y: 100 }, {
onComplete: () => {
animate(a, { scale: 1.2 })
}
})
}
})
Такая структура формирует цепочку, где каждый шаг начинается строго после завершения предыдущего.
onComplete не создаёт дополнительной нагрузки на каждый
кадр, так как вызывается единожды. Однако при массовом создании анимаций
важно учитывать:
onComplete снижает
читаемость,В SSR-сценариях onComplete не выполняется на сервере,
так как отсутствует жизненный цикл анимации. Callback активируется
только в браузерной среде после гидратации и старта анимации.
animate(card, { rotateY: 180 }, {
onComplete: () => {
card.classList.add("flipped")
}
})
animate(scene1, { opacity: 0 }, {
onComplete: () => animate(scene2, { opacity: 1 })
})
animate(button, { scale: 1.1 }, {
onComplete: () => {
button.style.transform = ""
}
})
При повторном запуске анимации на том же элементе предыдущий
onComplete может быть проигнорирован, если старая анимация
была заменена новой. Это связано с тем, что Motion One привязывает
callback к конкретному экземпляру анимации, а не к DOM-элементу.
onComplete выступает как точка синхронизации между
визуальным слоем и логикой приложения. Его использование формирует
чёткое разделение:
onComplete фиксирует переход в состоянии
приложения