Цепочки вызовов и синтаксис

Библиотека mo.js строится вокруг декларативного описания анимаций и их композиции через цепочки вызовов. Основной синтаксический стиль ориентирован на fluent API, где каждый метод возвращает объект, позволяющий продолжать конфигурацию без разрыва контекста. Такой подход формирует линейные и вложенные цепочки, которые одновременно описывают структуру анимации и порядок её исполнения.

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

const tween = new mojs.Tween({
  duration: 1000,
  easing: 'ease.out'
}).add({
  delay: 200,
  duration: 500
});

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

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

Базовая структура цепочек

Типичная цепочка в mo.js включает три уровня:

  • создание сущности (Tween, Shape, Timeline)
  • конфигурационные методы
  • методы запуска и управления

Пример структуры:

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

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

Метод then играет роль композиционного звена, соединяющего отдельные фазы анимации в одну цепь.

Цепочки в объектах Tween

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

const tween = new mojs.Tween()
  .add({
    duration: 300,
    delay: 100
  })
  .setEasing('sin.out')
  .repeat(3)
  .play();

Каждый метод выполняет строго определённую функцию:

  • add расширяет конфигурацию
  • setEasing изменяет кривую интерполяции
  • repeat задаёт повторение
  • play запускает выполнение

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

Цепочки в Shape-анимациях

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

const burst = new mojs.Burst({
  radius: { 0: 100 },
  count: 10
}).then({
  radius: { 100: 120 },
  duration: 600
}).replay();

Здесь цепочка формирует фазовую структуру:

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

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

Цепочки и композиция Timeline

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

const timeline = new mojs.Timeline();

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

  new mojs.Tween({
    delay: 200,
    duration: 800
  })
).play();

Цепочка здесь распространяется не только на один объект, но и на коллекцию анимаций. Методы add и play формируют глобальную структуру исполнения.

Timeline позволяет:

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

Вложенные цепочки и композиционные конструкции

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

const complex = new mojs.Timeline()
  .add(
    new mojs.Shape({
      radius: { 0: 30 }
    }).then({
      radius: { 30: 0 }
    })
  )
  .add(
    new mojs.Tween({
      duration: 1000
    }).setEasing('quad.inOut')
  )
  .play();

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

Возвращаемые значения и непрерывность цепочек

Основа цепочного синтаксиса заключается в гарантии возврата объекта текущего контекста. Это обеспечивает непрерывность вызовов:

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

Нарушение этой логики разрывает цепочку и требует промежуточных переменных, что противоречит стилю библиотеки.

const anim = new mojs.Shape({
  radius: 50
}).setOpacity(0.5)
  .setDuration(1000)
  .play();

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

Методы модификации внутри цепочек

Цепочный синтаксис опирается на набор стандартных методов модификации:

  • set — установка параметров
  • then — добавление следующей фазы
  • add — расширение композиции
  • play, replay, pause — управление жизненным циклом

Особое значение имеет метод then, который формирует переход между состояниями:

new mojs.Shape({
  radius: { 0: 20 }
}).then({
  radius: { 20: 60 }
}).then({
  radius: { 60: 10 }
}).play();

Цепочка then создаёт последовательность ключевых кадров без необходимости явного описания таймлайна.

Чистота выражений и декларативность

Цепочки вызовов в mo.js выполняют роль декларативного описания поведения. Логика исполнения отделена от структуры описания:

  • описание анимации строится как выражение
  • выполнение происходит после вызова управляющего метода
new mojs.Tween({
  duration: 500
})
.setEasing('cubic.out')
.repeat(2)
.play();

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

Ограничения цепочного синтаксиса

Несмотря на гибкость, цепочки накладывают определённые ограничения:

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

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

Композиция цепочек в масштабных анимациях

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

const part1 = new mojs.Shape({
  radius: { 0: 40 }
}).then({
  radius: { 40: 0 }
});

const part2 = new mojs.Tween({
  duration: 1200
}).setEasing('expo.out');

new mojs.Timeline()
  .add(part1, part2)
  .play();

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

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