Директивы для анимаций

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

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


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

Одной из ключевых директив является управление временем выполнения анимации. В Popmotion это достигается через параметры:

  • duration
  • elapsed
  • progress

Пример:

import { tween } from "popmotion";

tween({
  from: 0,
  to: 100,
  duration: 1000
}).start(v => console.log(v));

Здесь директива времени задаёт линейное изменение значения за 1 секунду.

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

  • duration определяет общий цикл
  • elapsed может использоваться для синхронизации
  • progress (0–1) позволяет управлять состоянием анимации вручную

Директивы easing-функций

Функции сглаживания задают характер движения. Они выступают как директивы, определяющие, как именно изменяется значение во времени.

В Popmotion доступны:

  • easeIn
  • easeOut
  • easeInOut
  • кастомные cubic-bezier

Пример:

import { tween, easing } from "popmotion";

tween({
  from: 0,
  to: 300,
  ease: easing.easeInOut
}).start(v => console.log(v));

Ключевая идея: директива ease меняет распределение скорости без изменения длительности.


Последовательные директивы (sequence)

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

import { chain, tween } from "popmotion";

chain(
  tween({ to: 100 }),
  tween({ to: 0 })
).start(v => console.log(v));

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

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

Параллельные директивы (parallel)

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

import { parallel, tween } from "popmotion";

parallel(
  tween({ to: 100 }),
  tween({ to: 200 })
).start(v => console.log(v));

Результат: возвращается массив значений, синхронизированных по времени.

Применение:

  • анимация нескольких свойств
  • синхронные переходы UI

Директивы циклов (loop)

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

import { loop, tween } from "popmotion";

loop(
  tween({ from: 0, to: 100, duration: 500 })
).start(v => console.log(v));

Возможности:

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

Директивы отражения (yoyo)

Эффект “туда-обратно” реализуется через отражение значений.

import { yoyo, tween } from "popmotion";

yoyo(
  tween({ from: 0, to: 100 })
).start(v => console.log(v));

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

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

Директивы задержки (delay)

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

import { delay, tween } from "popmotion";

delay(1000).start(() => {
  tween({ to: 100 }).start(v => console.log(v));
});

Назначение:

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

Директивы управления потоком (control flow)

Анимации в Popmotion можно рассматривать как потоки данных. Директивы управления потоком позволяют:

  • останавливать (stop)
  • перезапускать
  • переключать (switch)
  • фильтровать значения

Пример остановки:

const animation = tween({ to: 100 }).start(v => console.log(v));

// остановка через 500 мс
setTimeout(() => animation.stop(), 500);

Директивы интерполяции

Интерполяция определяет, как значения преобразуются между состояниями.

import { interpolate } from "popmotion";

const mixer = interpolate(
  [0, 1],
  ["#ff0000", "#0000ff"]
);

console.log(mixer(0.5));

Возможности:

  • числа
  • цвета
  • строки
  • сложные структуры

Интерполяция выступает директивой соответствия входного и выходного диапазона.


Директивы физических моделей

Анимации могут быть не только временными, но и физическими.

import { spring } from "popmotion";

spring({
  from: 0,
  to: 100,
  stiffness: 200,
  damping: 10
}).start(v => console.log(v));

Параметры:

  • stiffness — жёсткость
  • damping — затухание
  • mass — масса

Такие директивы описывают поведение системы, а не конкретную длительность.


Комбинирование директив

Главная сила Popmotion — в композиции.

import { chain, delay, tween, loop, yoyo } from "popmotion";

chain(
  delay(500),
  loop(
    yoyo(
      tween({ from: 0, to: 100, duration: 300 })
    )
  )
).start(v => console.log(v));

Здесь одновременно используются:

  • задержка
  • цикл
  • отражение
  • последовательность

Это позволяет описывать сложные анимационные сценарии декларативно и компактно.


Директивы реактивности

Анимации могут реагировать на внешние события:

  • пользовательский ввод
  • скролл
  • изменения состояния
import { value, tween } from "popmotion";

const val = value(0, v => console.log(v));

document.addEventListener("click", () => {
  tween({ from: val.get(), to: 100 }).start(val);
});

Смысл: значение становится реактивным источником, а анимация — директивой его изменения.


Директивы композиции значений

Popmotion позволяет объединять несколько потоков:

import { composite, tween } from "popmotion";

composite({
  x: tween({ to: 100 }),
  y: tween({ to: 200 })
}).start(v => console.log(v));

Результат:

{ x: ..., y: ... }

Это особенно важно для работы с:

  • transform
  • позиционированием
  • комплексными стилями

Практические паттерны

1. Пульсация:

loop(
  yoyo(
    tween({ from: 1, to: 1.2, duration: 300 })
  )
)

2. Появление с задержкой:

chain(
  delay(300),
  tween({ from: 0, to: 1 })
)

3. Имитация физики:

spring({ to: 0 })

Архитектурный смысл директив

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

  • Абстракция — избавляют от ручного управления кадрами
  • Композиция — позволяют строить сложные системы из простых блоков
  • Декларативность — описывается поведение, а не процесс
  • Реактивность — легко интегрируются с событиями

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