Методы запуска и остановки

В библиотеке mo.js управление жизненным циклом анимации строится вокруг унифицированных методов, применяемых ко всем основным сущностям: Tween, Timeline, Shape, Burst. Независимо от типа объекта, запуск и остановка анимации контролируются через единый интерфейс, что обеспечивает предсказуемое поведение в сложных композициях.

Каждая анимация существует в одном из состояний: подготовка, выполнение, остановка, завершение. Переход между состояниями осуществляется программно и может быть синхронизирован с другими анимациями через таймлайны.


Метод start()

Метод start() инициирует выполнение анимации. Он применяется ко всем анимационным объектам и отвечает за перевод состояния в активное.

Базовое поведение

При вызове start() происходит:

  • установка начального времени анимации
  • активация внутреннего тикера
  • запуск интерполяции значений
  • подключение к requestAnimationFrame-циклу
const circle = new mojs.Shape({
  shape: 'circle',
  radius: 40,
  fill: 'cyan',
  duration: 1000
});

circle.start();

Повторный запуск

Повторный вызов start() перезапускает анимацию с начальных значений. Это поведение особенно важно при работе с интерактивными элементами:

const burst = new mojs.Burst({
  radius: { 0: 100 },
  count: 10
});

document.addEventListener('click', () => {
  burst.start();
});

Каждый новый запуск создает независимый цикл воспроизведения, не требующий пересоздания объекта.

Особенности поведения в Timeline

При использовании Timeline метод start() запускает всю группу анимаций синхронно:

const timeline = new mojs.Timeline();

timeline.add([
  new mojs.Shape({ shape: 'circle', radius: 20 }),
  new mojs.Shape({ shape: 'rect', radius: 20 })
]);

timeline.start();

В этом случае старт происходит каскадно, но управляется единым временным контекстом.


Метод stop()

Метод stop() завершает текущее выполнение анимации и переводит её в неактивное состояние.

Основное поведение

При вызове stop():

  • прекращается интерполяция значений
  • отключается обновление через requestAnimationFrame
  • анимация фиксируется на текущем кадре
  • внутренний таймер сбрасывается
const anim = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 50 },
  duration: 2000
});

anim.start();

setTimeout(() => {
  anim.stop();
}, 1000);

Фиксация состояния

Ключевая особенность stop() заключается в сохранении текущего визуального состояния. Объект не возвращается в исходное положение автоматически.

anim.stop(); // объект остается в текущем размере и положении

Это поведение позволяет создавать эффекты “заморозки” кадра в интерактивных интерфейсах.


Различие между stop() и сбросом состояния

stop() не эквивалентен полному сбросу. После остановки:

  • начальные параметры сохраняются
  • прогресс анимации фиксируется
  • повторный start() запускает с начала, а не с точки остановки (в стандартной конфигурации)

Для сброса состояния используется комбинация ручного управления свойствами или пересоздание объекта.


Управление анимацией через повторные циклы

При частом вызове start() и stop() возникает необходимость учитывать состояние экземпляра.

Типичный цикл взаимодействия

const anim = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 80 },
  duration: 600
});

button.addEventListener('mousedown', () => anim.start());
button.addEventListener('mouseup', () => anim.stop());

В таком режиме создается эффект “нажатия”, где start() активирует рост, а stop() фиксирует текущее значение.


Поведение в сложных композициях

В композициях с несколькими слоями анимаций методы start() и stop() могут применяться как к отдельным элементам, так и к контейнеру.

Запуск группы

const shape1 = new mojs.Shape({ radius: 20 });
const shape2 = new mojs.Shape({ radius: 40 });

const timeline = new mojs.Timeline();
timeline.add(shape1, shape2);

timeline.start();

Запуск таймлайна эквивалентен одновременному вызову start() для всех вложенных анимаций.

Остановка группы

timeline.stop();

Останавливает все дочерние анимации без необходимости обращения к каждому объекту.


Повторный старт после остановки

После вызова stop() объект может быть снова запущен без пересоздания:

anim.start();
anim.stop();
anim.start();

Каждый новый start() инициирует новый цикл, независимо от предыдущего состояния.


Взаимодействие с длительностью и прогрессом

Методы управления тесно связаны с параметром duration. При остановке:

  • таймер останавливается
  • оставшееся время игнорируется
  • прогресс фиксируется

При новом запуске duration применяется заново.


Синхронизация start() и stop() в интерактивных сценариях

В интерактивной графике часто используется управление через события интерфейса:

const anim = new mojs.Shape({
  shape: 'rect',
  radius: { 10: 60 },
  duration: 800
});

element.addEventListener('mouseenter', () => anim.start());
element.addEventListener('mouseleave', () => anim.stop());

Такой подход позволяет формировать реактивные визуальные эффекты без сложной логики состояния.


Частые ошибки при управлении состоянием

Многократный start без stop

При частом вызове start() без остановки предыдущего цикла могут возникать наложения анимаций:

  • визуальное дублирование эффектов
  • увеличение нагрузки на requestAnimationFrame
  • непредсказуемые промежуточные состояния

Остановка до инициализации

Вызов stop() до start() обычно не вызывает эффекта, так как нет активного цикла.

Использование stop вместо reset

stop() не возвращает объект в исходное состояние, что часто приводит к логическим ошибкам при повторной анимации интерфейса.


Сочетание с управлением таймлайнами

В сложных сценах таймлайн выступает как централизованный контроллер:

  • start() активирует весь граф анимаций
  • stop() мгновенно прекращает все процессы
  • вложенные анимации не требуют отдельного управления
const tl = new mojs.Timeline();

tl.add([
  new mojs.Shape({ radius: 20 }),
  new mojs.Shape({ radius: 50 })
]);

tl.start();
setTimeout(() => tl.stop(), 1200);

Поведение при асинхронных событиях

В условиях асинхронного управления (например, событий мыши, таймеров, API событий) методы start() и stop() работают как идемпотентные операции:

  • start() всегда инициирует новый цикл
  • stop() всегда завершает текущий

Это позволяет безопасно вызывать их без проверки состояния.