setProgress() - установка позиции

Метод setProgress() в библиотеке mo.js используется для ручного управления состоянием анимации, позволяя установить её на конкретную позицию во временной шкале. Это один из ключевых инструментов при создании интерактивных интерфейсов, где анимация должна синхронизироваться с действиями пользователя или внешними событиями.

В отличие от автоматического воспроизведения (play()), данный метод даёт полный контроль над текущим кадром анимации.


Базовый синтаксис

tween.setProgress(progress);

Параметры:

  • progress — число от 0 до 1, где:

    • 0 — начало анимации
    • 1 — завершение анимации
    • промежуточные значения — соответствующая доля выполнения

Принцип работы

В основе mo.js лежит концепция временной шкалы (timeline). Любая анимация интерполирует значения свойств от начального к конечному состоянию.

Метод setProgress() напрямую задаёт положение на этой шкале:

  • вычисляются текущие значения всех анимируемых свойств
  • применяется easing-функция
  • обновляется DOM или canvas

Важно: метод не запускает анимацию, а лишь устанавливает её состояние.


Пример: управление позицией круга

const circle = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 50 },
  duration: 1000
});

// Установить анимацию на середину
circle.setProgress(0.5);

Результат:

  • радиус круга будет равен значению, соответствующему 50% анимации
  • easing уже применён

Связь с easing-функциями

При использовании setProgress() значение progress не равно линейному переходу свойств, если задан easing.

const tween = new mojs.Tween({
  duration: 1000,
  easing: 'elastic.out',
  onUpdate: (p) => {
    console.log(p);
  }
});

tween.setProgress(0.5);

Здесь:

  • 0.5 передаётся как вход easing-функции
  • фактическое значение может быть, например, 0.8 или даже больше (в случае “перелёта”)

Отличие от setProgress и play

Метод Назначение
play() Запуск анимации
pause() Пауза
setProgress() Установка конкретного состояния

Использование с Timeline

При работе с mojs.Timeline метод setProgress() применяется ко всей группе анимаций:

const timeline = new mojs.Timeline();

timeline.add(circle1, circle2);

// Установить прогресс всей последовательности
timeline.setProgress(0.25);

Все дочерние анимации:

  • синхронизируются
  • получают соответствующее состояние

Интерактивное управление (scroll, drag)

Один из самых распространённых сценариев — привязка анимации к пользовательскому вводу.

Пример: scroll-анимация

window.addEventListener('scroll', () => {
  const scrollTop = window.scrollY;
  const maxScroll = document.body.scrollHeight - window.innerHeight;

  const progress = scrollTop / maxScroll;

  tween.setProgress(progress);
});

Особенности:

  • анимация не воспроизводится, а «следует» за прокруткой
  • отсутствует временной фактор — только положение

Ограничения значений

Метод ожидает значения в диапазоне [0, 1], но:

  • значения < 0 интерпретируются как 0
  • значения > 1 — как 1 (или могут вызывать перерасчёт в зависимости от easing)

Рекомендуется явно ограничивать диапазон:

const progress = Math.min(Math.max(value, 0), 1);
tween.setProgress(progress);

Поведение при повторных вызовах

Каждый вызов setProgress():

  • полностью пересчитывает состояние
  • не зависит от предыдущего вызова
  • не накапливает изменения

Это делает метод детерминированным — одинаковый вход всегда даёт одинаковый результат.


Работа с задержками (delay)

Если у анимации задан delay, метод setProgress() учитывает его:

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

tween.setProgress(0.2);

Фактически:

  • первые 500 мс — “пустое” время
  • прогресс распределяется по общей длительности (delay + duration)

Синхронизация нескольких анимаций

setProgress() удобно использовать для синхронного управления несколькими объектами:

const shapes = [shape1, shape2, shape3];

function update(progress) {
  shapes.forEach(shape => shape.setProgress(progress));
}

Это позволяет:

  • создавать сложные сцены
  • управлять ими единым параметром

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

Метод часто применяется при создании собственных контроллеров:

Пример: ползунок

input.addEventListener('input', (e) => {
  const value = e.target.value / 100;
  tween.setProgress(value);
});

Производительность

setProgress():

  • выполняет синхронный пересчёт
  • может быть затратным при большом количестве объектов

Рекомендации:

  • избегать частых вызовов (например, в mousemove)
  • использовать requestAnimationFrame
let progress = 0;

function update() {
  tween.setProgress(progress);
  requestAnimationFrame(update);
}

update();

Взаимодействие с onUpdate

При вызове setProgress() триггерится onUpdate:

const tween = new mojs.Tween({
  onUpdate: (p) => {
    console.log('progress:', p);
  }
});

tween.setProgress(0.7);

Это позволяет:

  • отслеживать состояние
  • синхронизировать внешние элементы

Частые ошибки

1. Ожидание запуска анимации

tween.setProgress(1); // не запускает, а сразу устанавливает конец

2. Игнорирование easing

// значение не будет линейным

3. Использование вне диапазона

tween.setProgress(5); // некорректное поведение

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

  • scroll-driven анимации
  • drag & drop эффекты
  • синхронизация с видео/аудио
  • кастомные UI-контроллеры
  • интерактивные презентации

Внутренняя логика

При вызове метода происходит:

  1. нормализация progress
  2. применение easing-функции
  3. вычисление текущих значений свойств
  4. обновление состояния объектов
  5. вызов колбэков (onUpdate)

Комбинирование с другими методами

tween
  .setProgress(0.3)
  .pause();

или:

tween.setProgress(0).play();

Такой подход позволяет:

  • устанавливать стартовую позицию
  • затем запускать анимацию

Управление обратным направлением

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

tween.setProgress(1 - progress);

Итоговая роль метода

setProgress() превращает анимацию из временного процесса в управляемое состояние. Это фундаментальный инструмент для создания динамических и интерактивных интерфейсов, где анимация становится частью логики приложения, а не просто визуальным эффектом.