Сегментная анимация в Popmotion строится на идее разбиения движения на отдельные участки, каждый из которых может иметь собственные параметры интерполяции. Вместо единого криволинейного изменения значения используется набор фаз, где каждая фаза описывается своей скоростью, длительностью и функцией смягчения. Такой подход позволяет создавать сложные движения, которые невозможно выразить одной easing-функцией.
В Popmotion ключевым инструментом для сегментированного движения выступают keyframes. Они позволяют задать массив значений и сопоставить им временные точки, формируя дискретные участки траектории.
Каждый сегмент определяется парой соседних ключевых значений. Например, если заданы значения:
то формируются два сегмента:
Именно к этим переходам применяется логика easing.
Основная особенность Popmotion заключается в том, что массив easing может соответствовать массиву сегментов. Это означает, что каждый переход между ключевыми точками может иметь собственную функцию интерполяции.
Структура сопоставления выглядит следующим образом:
import { keyframes } from 'popmotion';
const animation = keyframes({
values: [0, 100, 50],
duration: 2000,
easings: [
easeOut, // 0 → 100
easeIn // 100 → 50
]
});
Количество easing-функций всегда равно количеству сегментов, то есть
values.length - 1.
Такой подход позволяет управлять характером движения на каждом участке отдельно, создавая неоднородную динамику.
Каждый сегмент интерпретируется независимо. Это означает, что easing-функция применяется не ко всей анимации целиком, а к нормализованному времени конкретного отрезка.
Если обозначить:
то внутри сегмента время приводится к диапазону [0, 1], и уже затем применяется easing:
progress = easing((t - t₁) / (t₂ - t₁))
Такой механизм гарантирует, что каждый участок сохраняет собственную кривую ускорения без влияния соседних фаз.
В одном наборе сегментов могут сочетаться принципиально разные типы функций:
Пример с разнообразной динамикой:
import { keyframes, easeIn, easeOut, linear } from 'popmotion';
const motion = keyframes({
values: [0, 300, 150, 400],
duration: 3000,
easings: [
easeOut, // быстрый старт
linear, // равномерное движение
easeIn // плавное завершение с ускорением
]
});
Первый сегмент задаёт энергичный старт, второй — стабилизацию движения, третий — ускоренное завершение.
Хотя easing влияет на форму кривой, визуальное восприятие сильно зависит от длительности сегмента. Короткие сегменты с сильным easing создают резкие скачки, тогда как длинные сглаживают даже агрессивные функции.
Распределение времени может быть задано через times:
const animation = keyframes({
values: [0, 100, 200],
times: [0, 0.2, 1],
duration: 2000,
easings: [easeOut, easeIn]
});
Здесь первый сегмент занимает 20% времени всей анимации, второй — оставшиеся 80%. Это усиливает контраст между фазами движения.
Помимо встроенных вариантов Popmotion поддерживает передачу произвольных функций. Это позволяет реализовать уникальные модели ускорения.
Функция easing принимает значение от 0 до 1 и возвращает трансформированное значение в том же диапазоне.
Пример нелинейной функции:
const customEase = t => Math.pow(t, 3);
const animation = keyframes({
values: [0, 500],
duration: 1000,
easings: [customEase]
});
В сегментной модели такие функции могут быть распределены по разным участкам:
const motion = keyframes({
values: [0, 200, 600],
duration: 2000,
easings: [
t => t * t, // мягкое ускорение
t => 1 - Math.pow(1 - t, 3) // резкое замедление
]
});
При использовании разных easing-функций в соседних сегментах возможны визуальные разрывы динамики. Это не ошибка, а следствие смены модели интерполяции.
Сглаживание таких переходов достигается за счёт:
Сегментное easing часто используется для имитации реальных физических процессов:
Пример движения с эффектом удара:
const impact = keyframes({
values: [0, 300, 260, 280],
duration: 1500,
easings: [
easeOut, // резкий разгон
easeIn, // удар и возврат
easeOut // затухающий отскок
]
});
Каждый сегмент моделирует отдельную фазу физического поведения, формируя сложную траекторию без необходимости вручную рассчитывать физику.
Сегментные easing позволяют формировать ритмику движения. Повторяющиеся паттерны easing создают ощущение цикличности, тогда как чередование противоположных функций формирует напряжение.
Пример ритмического паттерна:
const rhythm = keyframes({
values: [0, 100, 0, 100, 0],
duration: 2500,
easings: [
easeInOut,
easeInOut,
easeInOut,
easeInOut
]
});
Хотя easing одинаковый, изменение направлений сегментов создаёт визуальный пульсирующий эффект.
При увеличении количества сегментов растёт контроль над движением, но усложняется прогнозирование результата. Каждый дополнительный сегмент изменяет общую динамику всей цепочки, особенно при использовании разных easing-функций.
В таких случаях важным становится не только выбор easing, но и их последовательность. Резкие функции лучше размещать ближе к началу, плавные — ближе к завершению, если требуется естественное затухание движения.