Создание временной шкалы

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

Основная идея заключается в том, что каждый tween или shape может существовать самостоятельно, но при включении в timeline начинает подчиняться общей временной сетке. Это позволяет выстраивать как простые последовательности, так и многослойные анимационные системы с перекрывающимися фазами.

Создание timeline в mo.js выполняется через конструктор mojs.Timeline. После инициализации он наполняется анимационными сущностями через метод add.

const timeline = new mojs.Timeline();

const circle = new mojs.Shape({
  parent: '#app',
  shape: 'circle',
  radius: { 0: 50 },
  fill: 'cyan',
  duration: 600
});

timeline.add(circle);

timeline.play();

Каждый добавленный элемент сохраняет собственные параметры длительности и задержки, но их запуск синхронизируется относительно стартовой точки timeline.

Последовательное и параллельное выполнение

Организация временной структуры определяется параметрами отдельных анимаций. При отсутствии задержек элементы стартуют одновременно, формируя параллельное воспроизведение.

const timeline = new mojs.Timeline();

const a = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 40 },
  duration: 500
});

const b = new mojs.Shape({
  shape: 'rect',
  radius: { 0: 40 },
  delay: 500,
  duration: 500
});

timeline.add(a, b);
timeline.play();

Задержка во втором элементе формирует последовательную структуру, при которой второй tween начинает работу после завершения первого.

Управление длительностью и синхронизацией

Каждый элемент timeline может иметь параметры duration, delay, repeat, влияющие на общую композицию. Суммарная длительность timeline не задаётся напрямую, а вычисляется как максимум всех вложенных временных интервалов.

const timeline = new mojs.Timeline();

const segment1 = new mojs.Shape({
  radius: { 0: 30 },
  duration: 400
});

const segment2 = new mojs.Shape({
  radius: { 0: 60 },
  delay: 200,
  duration: 600
});

timeline.add(segment1, segment2);

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

Вложенные timelines

Timeline может содержать другие timeline, формируя иерархическую структуру анимаций. Такой подход используется для группировки логически связанных сцен.

const inner = new mojs.Timeline();

const part1 = new mojs.Shape({
  radius: { 0: 20 },
  duration: 300
});

const part2 = new mojs.Shape({
  radius: { 0: 40 },
  delay: 150,
  duration: 300
});

inner.add(part1, part2);

const main = new mojs.Timeline();
main.add(inner);

main.play();

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

Управление воспроизведением

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

  • play() — запуск с текущей позиции
  • replay() — перезапуск с начала
  • pause() — остановка на текущем кадре
  • stop() — полная остановка с возвратом к начальному состоянию
const timeline = new mojs.Timeline();

timeline.add(new mojs.Shape({
  radius: { 0: 50 },
  duration: 800
}));

timeline.play();
timeline.pause();
timeline.replay();

Поведение replay особенно важно в интерфейсных сценариях, где требуется повторная синхронизация без пересоздания объектов.

Координация нескольких эффектов

Timeline позволяет объединять разные типы анимаций: формы, твины, burst-эффекты. Это создаёт единое временное пространство, где визуальные элементы взаимодействуют синхронно.

const burst = new mojs.Burst({
  radius: { 0: 100 },
  count: 10,
  children: {
    shape: 'circle',
    radius: { 0: 20 },
    duration: 600
  }
});

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

const timeline = new mojs.Timeline();
timeline.add(circle, burst);

timeline.play();

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

Stagger-поведение и временные смещения

Хотя mo.js не предоставляет отдельного stagger API в timeline, аналогичный эффект достигается через динамическое вычисление задержек.

const timeline = new mojs.Timeline();

const items = Array.from({ length: 5 }).map((_, i) =>
  new mojs.Shape({
    radius: { 0: 30 },
    delay: i * 100,
    duration: 400
  })
);

timeline.add(...items);
timeline.play();

Такой подход формирует каскадное появление элементов, при котором каждый следующий tween смещён во времени относительно предыдущего.

Повторение и циклические сценарии

Timeline поддерживает повторное воспроизведение через параметр repeat. Это позволяет создавать циклические анимации без внешнего управления состоянием.

const timeline = new mojs.Timeline({
  repeat: 2
});

timeline.add(
  new mojs.Shape({
    radius: { 0: 40 },
    duration: 500
  })
);

timeline.play();

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

Управление скоростью воспроизведения

Скорость выполнения timeline может изменяться через свойство speed. Это влияет на все вложенные анимации одновременно, сохраняя относительные временные пропорции.

const timeline = new mojs.Timeline();

timeline.add(
  new mojs.Shape({
    radius: { 0: 60 },
    duration: 1000
  })
);

timeline.speed(2);
timeline.play();

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

Сложные композиции с пересечением фаз

Перекрывающиеся анимации позволяют формировать многослойные эффекты, где одна фаза начинается до завершения другой. Это достигается комбинацией delay и различной длительности элементов.

const timeline = new mojs.Timeline();

timeline.add(
  new mojs.Shape({
    radius: { 0: 30 },
    duration: 600
  }),
  new mojs.Shape({
    radius: { 0: 60 },
    delay: 200,
    duration: 600
  }),
  new mojs.Shape({
    radius: { 0: 90 },
    delay: 400,
    duration: 600
  })
);

timeline.play();

Такая структура формирует эффект нарастающей волны, где визуальные состояния накладываются друг на друга.

Привязка timeline к событиям интерфейса

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

const timeline = new mojs.Timeline();

timeline.add(
  new mojs.Shape({
    radius: { 0: 50 },
    duration: 500
  })
);

document.addEventListener('click', () => {
  timeline.replay();
});

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

Организация масштабируемых анимационных систем

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

Разделение на под-timeline позволяет избегать линейного усложнения кода и сохранять временную структуру читаемой даже при десятках анимационных элементов.

const intro = new mojs.Timeline();
const loop = new mojs.Timeline();

intro.add(new mojs.Shape({ radius: { 0: 40 }, duration: 400 }));
loop.add(new mojs.Shape({ radius: { 0: 20 }, duration: 300 }));

const main = new mojs.Timeline();
main.add(intro, loop);

main.play();