onStart

Событие onStart в библиотеке mo.js используется для перехвата момента начала анимации. Оно вызывается ровно в тот момент, когда объект анимации запускается, и позволяет выполнить произвольную логику до того, как начнётся визуальное изменение свойств.

Ключевая особенность — onStart срабатывает один раз при каждом запуске анимации, в отличие от других событий, таких как onUpdate, которые вызываются многократно в процессе проигрывания.


Синтаксис и базовое использование

Свойство onStart передаётся в конфигурационный объект при создании любого анимируемого элемента, например mojs.Tween, mojs.Shape, mojs.Burst и других.

const tween = new mojs.Tween({
  duration: 1000,
  onStart() {
    console.log('Анимация началась');
  }
});

Допускается использование стрелочной функции:

const tween = new mojs.Tween({
  duration: 1000,
  onStart: () => {
    console.log('Старт анимации');
  }
});

Контекст выполнения

Внутри обработчика onStart доступен контекст текущего анимируемого объекта через this. Это позволяет взаимодействовать с его параметрами и методами.

const shape = new mojs.Shape({
  radius: 50,
  duration: 1000,
  onStart() {
    console.log(this); // ссылка на текущий Shape
  }
});

Контекст особенно полезен при динамическом изменении свойств:

const shape = new mojs.Shape({
  radius: 50,
  fill: 'red',
  duration: 1000,
  onStart() {
    this.el.style.backgroundColor = 'blue';
  }
});

Практическое применение

1. Инициализация состояния

Перед запуском анимации часто требуется подготовить DOM или внутренние данные:

const shape = new mojs.Shape({
  radius: 30,
  duration: 800,
  onStart() {
    document.body.classList.add('animation-started');
  }
});

2. Синхронизация с другими процессами

onStart позволяет синхронизировать анимацию с логикой приложения:

const tween = new mojs.Tween({
  duration: 500,
  onStart() {
    startSoundEffect();
  }
});

3. Логирование и отладка

При разработке сложных анимационных сценариев важно отслеживать жизненный цикл:

const burst = new mojs.Burst({
  count: 10,
  duration: 1200,
  onStart() {
    console.log('Burst запущен');
  }
});

4. Управление зависимыми анимациями

Можно запускать другие анимации в момент старта:

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

shape1.tune({
  onStart() {
    shape2.replay();
  }
});

Отличие от onUpdate и onComplete

Событие Момент вызова Частота вызова
onStart При запуске анимации Один раз
onUpdate Во время выполнения На каждом кадре
onComplete После завершения Один раз

onStart используется для начальной логики, тогда как onUpdate — для динамических вычислений, а onComplete — для завершения сценария.


Поведение при повторном запуске

При каждом вызове методов:

  • .play()
  • .replay()
  • .restart()

обработчик onStart будет вызываться заново.

tween.play();   // вызовет onStart
tween.replay(); // снова вызовет onStart

Это делает событие удобным для повторяемых анимаций.


Особенности работы с Timeline

В составе mojs.Timeline событие onStart каждого элемента срабатывает независимо, в соответствии с его позицией на временной шкале.

const shape = new mojs.Shape({
  delay: 500,
  duration: 1000,
  onStart() {
    console.log('Shape начался после задержки');
  }
});

const timeline = new mojs.Timeline();
timeline.add(shape);
timeline.play();

onStart выполнится с учётом delay.


Комбинирование с delay

Событие onStart срабатывает после задержки, а не сразу после вызова .play().

const shape = new mojs.Shape({
  delay: 1000,
  duration: 500,
  onStart() {
    console.log('Запуск после 1 секунды');
  }
});

Использование с динамическими параметрами

onStart может применяться для изменения параметров перед началом анимации:

const shape = new mojs.Shape({
  radius: { 0: 50 },
  duration: 1000,
  onStart() {
    this._props.radius = { 0: Math.random() * 100 };
  }
});

Ошибки и подводные камни

1. Ожидание немедленного выполнения

onStart не вызывается при создании объекта — только при запуске анимации.


2. Потеря контекста в стрелочных функциях

Стрелочные функции не имеют собственного this:

onStart: () => {
  console.log(this); // не будет ссылаться на mo.js объект
}

Для доступа к экземпляру лучше использовать обычную функцию.


3. Изменение DOM без учёта производительности

Часто onStart используют для манипуляций с DOM. При большом количестве анимаций это может привести к задержкам:

onStart() {
  document.body.style.background = 'red';
}

Следует минимизировать тяжёлые операции.


Расширенные сценарии

Условный запуск логики

const tween = new mojs.Tween({
  duration: 1000,
  onStart() {
    if (shouldAnimate) {
      console.log('Разрешено');
    }
  }
});

Интеграция с внешними библиотеками

const shape = new mojs.Shape({
  duration: 800,
  onStart() {
    gsap.to('.box', { x: 100 });
  }
});

Работа с состоянием приложения

const tween = new mojs.Tween({
  duration: 600,
  onStart() {
    appState.isAnimating = true;
  }
});

Внутренняя механика

При запуске анимации mo.js:

  1. Проверяет наличие delay
  2. Ждёт указанное время
  3. Вызывает onStart
  4. Запускает цикл обновления (onUpdate)
  5. После завершения вызывает onComplete

Это означает, что onStart является точкой входа в жизненный цикл анимации.


Использование в пользовательских компонентах

В архитектуре компонентных интерфейсов onStart часто применяется для уведомления о начале анимации:

class AnimatedButton {
  constructor() {
    this.animation = new mojs.Shape({
      duration: 300,
      onStart: () => this.handleStart()
    });
  }

  handleStart() {
    console.log('Кнопка анимируется');
  }
}

Связка с пользовательскими событиями

button.addEventListener('click', () => {
  shape.replay();
});
const shape = new mojs.Shape({
  duration: 500,
  onStart() {
    console.log('Анимация запущена по клику');
  }
});

Рекомендации по использованию

  • использовать для инициализации, а не для вычислений
  • избегать тяжёлых операций
  • применять для синхронизации анимаций
  • учитывать delay
  • не полагаться на стрелочные функции при работе с this

Сравнение с хуками в других библиотеках

По своей роли onStart аналогичен:

  • start в GSAP
  • begin в anime.js

Однако в mo.js он строго привязан к моменту фактического старта с учётом задержек, что делает его более предсказуемым при сложных таймлайнах.


Поведение при остановке и повторном запуске

Если анимация была остановлена (.pause()), а затем продолжена (.play()), onStart не будет вызван повторно, так как анимация уже была инициирована.

Повторный вызов происходит только при полном перезапуске:

tween.pause();
tween.play();   // onStart не вызовется

tween.replay(); // onStart вызовется снова

Использование с кастомными tween-объектами

const customTween = new mojs.Tween({
  duration: 1000,
  onStart() {
    console.log('Кастомный tween стартовал');
  },
  onUpdate(progress) {
    console.log(progress);
  }
});

Итоговая роль onStart в архитектуре анимаций

onStart выступает в роли:

  • точки инициализации
  • триггера синхронизации
  • средства контроля жизненного цикла
  • инструмента интеграции с внешней логикой

Его правильное использование позволяет строить предсказуемые, управляемые и масштабируемые анимационные системы.