Повторяющиеся анимации в Motion One управляются через параметр
repeat, а поведенческие хуки циклов — через
onRepeat. Этот колбэк вызывается каждый раз, когда анимация
завершает один цикл и начинает следующий, что делает его ключевым
инструментом для синхронизации состояния приложения с бесконечными или
многократными анимациями.
Механика повторения в Motion One строится вокруг пересоздания или переинициализации прогресса анимации после завершения одного цикла. При этом:
onRepeat срабатывает только при переходе к
следующему циклуТипичная конфигурация повторения:
import { animate } from "motion";
animate(".box", {
x: 300
}, {
duration: 1,
repeat: Infinity
});
В этом случае анимация бесконечно циклирует, но без внешней реакции на факт повторения.
Параметр onRepeat добавляется в опции анимации и
получает контроль при каждом новом цикле:
animate(".box", {
rotate: 360
}, {
duration: 2,
repeat: Infinity,
onRepeat: () => {
console.log("цикл завершён, начинается новый");
}
});
Каждый вызов onRepeat соответствует моменту сброса
прогресса анимации.
Колбэк вызывается в рамках внутреннего цикла Motion One и не получает аргументов по умолчанию. Однако его поведение зависит от конфигурации повторения:
repeat: 0 → вызов отсутствуетrepeat: N → вызов происходит N разrepeat: Infinity → вызов происходит бесконечноrepeatType: "loop" → стандартное повторение с возвратом
к началуrepeatType: "reverse" → каждый цикл меняет
направлениеПример с конечным числом повторов:
animate(".line", {
width: "100%"
}, {
duration: 1,
repeat: 3,
onRepeat: () => {
console.log("очередной цикл завершён");
}
});
Поведение onRepeat напрямую связано с типом
повторения.
Стандартный режим, при котором анимация возвращается к начальному значению:
animate(".dot", {
x: 200
}, {
duration: 1,
repeat: Infinity,
repeatType: "loop",
onRepeat: () => {
// фиксируется каждый сброс прогресса
}
});
Анимация изменяет направление на каждом цикле:
animate(".dot", {
x: 200
}, {
duration: 1,
repeat: Infinity,
repeatType: "reverse",
onRepeat: () => {
// вызывается при каждом развороте направления
}
});
В режиме reverse логика циклов становится симметричной:
каждый повтор — это смена направления движения, а не возврат к
начальному состоянию.
Типичный сценарий — отслеживание количества завершённых циклов анимации. Для этого используется внешняя переменная:
let count = 0;
animate(".bar", {
scaleX: 1
}, {
duration: 0.5,
repeat: 10,
onRepeat: () => {
count += 1;
console.log("цикл:", count);
}
});
Такой подход применяется при:
При использовании onRepeat возможно обновление состояния
DOM или внешнего состояния приложения.
const indicator = document.querySelector(".indicator");
animate(".pulse", {
opacity: [0.2, 1]
}, {
duration: 0.8,
repeat: Infinity,
onRepeat: () => {
indicator.classList.toggle("active");
}
});
Каждый цикл анимации становится триггером для изменения визуального состояния интерфейса.
Motion One работает поверх Web Animations API, поэтому вызов
onRepeat зависит от планировщика браузера. Это приводит к
следующим особенностям:
playbackRate частота вызовов
масштабируетсяПример с ускорением:
animate(".orb", {
rotate: 360
}, {
duration: 2,
repeat: Infinity,
playbackRate: 2,
onRepeat: () => {
// вызывается вдвое чаще по времени
}
});
Если анимация останавливается вручную или удаляется, дальнейшие
вызовы onRepeat прекращаются:
const animation = animate(".square", {
x: 500
}, {
duration: 1,
repeat: Infinity,
onRepeat: () => {
console.log("цикл");
}
});
setTimeout(() => {
animation.stop();
}, 3000);
После остановки цикл разрывается и новые итерации не инициируются.
При использовании timeline повторение и
onRepeat применяются к отдельным анимационным сегментам или
всей последовательности в зависимости от структуры:
import { timeline } from "motion";
timeline([
[".a", { x: 100 }, { duration: 0.5 }],
[".b", { x: 200 }, { duration: 0.5 }]
], {
repeat: Infinity,
onRepeat: () => {
console.log("полный цикл timeline завершён");
}
});
Здесь каждый onRepeat соответствует завершению всей
цепочки анимаций.
Повторяющиеся события через onRepeat применяются в
системах, где важна цикличность:
Неправильная интерпретация поведения приводит к следующим проблемам:
onUpdate (срабатывает только
между циклами)repeatType на логикуInfinityКорректная модель восприятия заключается в том, что
onRepeat фиксирует не прогресс, а факт завершения цикла и
перехода к следующему.