setSpeed() - изменение скорости

mo.js содержит систему управления анимациями, основанную на двух ключевых сущностях: отдельные анимационные объекты (tween) и временные контейнеры (timeline). Управление скоростью воспроизведения в этой системе реализуется через метод setSpeed(), влияющий на темп проигрывания всей связанной цепочки анимаций без изменения их внутренней логики.

setSpeed() изменяет коэффициент временного масштабирования анимации. Этот коэффициент применяется к внутреннему таймеру, который рассчитывает прогресс анимации относительно времени выполнения.

Базовая логика:

  • значение 1 — нормальная скорость
  • значение < 1 — замедление
  • значение > 1 — ускорение
  • значение 0 — фактическая остановка прогресса времени

При изменении скорости не пересчитываются ключевые кадры, easing-функции или структура анимации. Изменяется только интерпретация времени.

Синтаксис применения

Метод применяется как к отдельным tween-объектам, так и к timeline:

tween.setSpeed(speed);
timeline.setSpeed(speed);

Параметр speed — числовое значение коэффициента.

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

Поведение в tween-объектах

Tween в mo.js представляет собой атомарную анимацию с ограниченным временем жизни. При вызове setSpeed():

  • длительность tween интерпретируется через новый коэффициент
  • текущая позиция времени масштабируется
  • анимация продолжает выполнение с новой скоростью без сброса состояния

Изменение скорости во время выполнения не вызывает перезапуск tween, а корректирует временную шкалу «на лету».

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

tween.play();
tween.setSpeed(2);

В данном случае фактическая длительность выполнения сокращается примерно вдвое.

Поведение в timeline

Timeline агрегирует несколько tween-объектов и синхронизирует их временную ось. При применении setSpeed() к timeline:

  • изменяется глобальная временная шкала
  • все вложенные анимации масштабируются пропорционально
  • сохраняются относительные задержки и последовательность
const timeline = new mojs.Timeline();

timeline.add(
  new mojs.Tween({ duration: 1000 }),
  new mojs.Tween({ duration: 1000, delay: 200 })
);

timeline.play();
timeline.setSpeed(0.5);

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

Динамическое управление скоростью

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

Особенность реализации:

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

Такой подход исключает рывки при изменении скорости.

timeline.play();

setTimeout(() => {
  timeline.setSpeed(0.25);
}, 500);

Анимация продолжает выполнение с новым временным масштабом без перезапуска.

Влияние на easing-функции

Easing-функции не модифицируются при изменении скорости. Они получают уже нормализованный прогресс (0–1), который зависит от скорректированного времени.

Это означает:

  • форма кривой остается неизменной
  • изменяется только скорость прохождения по кривой
  • визуальная динамика сохраняет характер easing

Таким образом, ускорение не делает easing более резким, а замедление не растягивает его математическую форму, а лишь увеличивает длительность прохождения.

Сочетание с цепочками анимаций

При работе с последовательными tween в timeline изменение скорости влияет на:

  • интервалы между анимациями
  • задержки (delay)
  • синхронизацию start/end событий

Если используется сложная композиция, основанная на нескольких timeline, setSpeed() может применяться иерархически:

  • внешний timeline влияет на все вложенные
  • внутренний tween может иметь собственный коэффициент скорости

Итоговая скорость становится произведением коэффициентов.

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

Динамическое управление скоростью часто применяется в реактивных интерфейсах:

  • замедление анимации при наведении
  • ускорение при взаимодействии пользователя
  • синхронизация с аудио или визуальными эффектами
  • создание эффекта «slow motion»
timeline.setSpeed(1);

element.addEventListener('mouseenter', () => {
  timeline.setSpeed(0.3);
});

element.addEventListener('mouseleave', () => {
  timeline.setSpeed(1);
});

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

Ограничения и особенности реализации

Поведение setSpeed() имеет ряд технических особенностей:

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

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

Масштабирование времени и синхронизация

В сложных анимационных графах изменение скорости через setSpeed() влияет на всю временную структуру:

  • абсолютные тайминги становятся относительными
  • задержки масштабируются
  • параллельные анимации сохраняют синхронность

Это делает метод инструментом управления глобальным темпом сцен, а не только отдельных эффектов.