Циклические keyframes

Модель повторяющихся ключевых кадров

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

Базовая идея заключается в том, что анимация рассматривается как функция времени:

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

Базовая структура keyframes

Keyframes задаются как последовательность значений:

import { keyframes } from "popmotion";

const animation = keyframes({
  values: [0, 100, 50, 200],
  duration: 2000
});

Поведение по умолчанию:

  • движение от 0 к 100
  • затем к 50
  • затем к 200
  • после завершения анимация останавливается

Цикличность в таком виде отсутствует, и добавляется отдельно.


Механизм повторения анимации

Повторение реализуется через параметр loop или обёртки повторного запуска.

import { keyframes, loop } from "popmotion";

const animation = loop(
  keyframes({
    values: [0, 100, 50, 200],
    duration: 2000
  })
);

Поведение:

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

Циклические keyframes в таком варианте формируют непрерывное движение без пауз.


Типы цикличности

1. Простой цикл (loop)

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

loop(
  keyframes({
    values: [0, 1, 0.5, 1],
    duration: 1000
  })
);

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

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

2. Зеркальный цикл (yoyo)

Зеркальная цикличность обеспечивает обратное воспроизведение keyframes.

import { keyframes, yoyo } from "popmotion";

const animation = yoyo(
  keyframes({
    values: [0, 100, 200],
    duration: 1500
  })
);

Модель поведения:

  • прямой проход: 0 → 100 → 200
  • обратный проход: 200 → 100 → 0
  • цикл повторяется

Зеркальная цикличность устраняет резкий скачок в начале цикла.


3. Ограниченное число повторений

Цикличность может быть дискретной:

import { keyframes, repeat } from "popmotion";

const animation = repeat(
  keyframes({
    values: [0, 50, 100],
    duration: 800
  }),
  5
);

Семантика:

  • последовательность воспроизводится 5 раз
  • после завершения анимация прекращается

Циклические keyframes и временная интерполяция

Внутри Popmotion keyframes интерполяция строится на нормализованной шкале времени:

  • время переводится в диапазон 0..1
  • каждый участок keyframes занимает часть этого диапазона
  • значения интерполируются между соседними точками

При циклизации происходит повторная нормализация:

t = (t % 1)

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

t = 1 - t

в зависимости от фазы цикла.


Использование offset для точного цикла

Keyframes могут быть определены с явными временными смещениями:

const animation = keyframes({
  values: [0, 100, 0],
  times: [0, 0.5, 1],
  duration: 1200
});

Циклическая интерпретация таких данных позволяет:

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

Циклические паттерны движения

Пульсация

loop(
  keyframes({
    values: [1, 1.3, 1],
    duration: 600
  })
);

Используется для:

  • масштабирования элементов интерфейса
  • индикации активности
  • визуальной обратной связи

Колебания

yoyo(
  keyframes({
    values: [-20, 20],
    duration: 800
  })
);

Используется для:

  • имитации физического движения
  • покачивания объектов
  • инерционных эффектов

Многокадровый цикл

loop(
  keyframes({
    values: [0, 50, 100, 50],
    duration: 1200
  })
);

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

  • создаётся сложная форма волны
  • цикл не симметричен
  • часто применяется для UI-анимаций

Синхронизация нескольких циклических keyframes

При работе с несколькими анимациями важно учитывать:

  • одинаковую длительность циклов
  • согласование фаз
  • одинаковую стратегию повторения

Пример синхронизации:

const a = loop(keyframes({ values: [0, 100], duration: 1000 }));
const b = loop(keyframes({ values: [100, 0], duration: 1000 }));

Результат:

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

Накопление ошибок при бесконечных циклах

При длительных циклах возможны:

  • дрейф времени из-за вычислений floating point
  • визуальные скачки при несогласованных easing-функциях
  • рассинхронизация при независимых таймерах

Компенсация достигается через:

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

Циклы и easing-функции

Easing внутри циклических keyframes влияет на форму повторения:

  • linear создаёт равномерное движение
  • easeIn/out формирует ускорение и замедление
  • bezier-кривые позволяют имитировать физические процессы

В цикле easing повторяется вместе с фазой анимации, что создаёт характерный «рисунок» движения.


Комбинирование циклических keyframes с transform-анимациями

Типичный сценарий:

loop(
  keyframes({
    values: [0, 360],
    duration: 2000
  })
);

Используется для:

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

Комбинация с scale и opacity позволяет создавать сложные составные циклы:

loop(
  keyframes({
    values: [0, 1, 0],
    duration: 900
  })
);

Архитектура повторяющейся keyframes-анимации

Циклическая keyframes-анимация в Popmotion строится из следующих компонентов:

  • генератор прогресса времени
  • интерполятор значений
  • механизм нормализации цикла
  • стратегия повторения (loop/yoyo/repeat)
  • easing-функция

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