Работа с градиентами в интерфейсной анимации опирается на непрерывные переходы между цветовыми состояниями. В Popmotion ключевой механизм здесь — интерполяция значений, при которой числовые или цветовые параметры преобразуются во времени по заданной кривой движения.
Цвет в анимации нельзя рассматривать как строку. Он раскладывается на компоненты: RGB, HSL или HSV. Popmotion оперирует числовыми значениями, поэтому любой градиент фактически сводится к набору анимируемых чисел.
Базовая идея:
Popmotion предоставляет механизм value, который хранит
изменяемое состояние и позволяет подписываться на его обновления. При
анимации градиентов это становится центральной точкой управления.
import { value, tween } from 'popmotion';
const color = value('rgb(255, 0, 0)', (v) => {
document.body.style.background = v;
});
tween({
from: 'rgb(255, 0, 0)',
to: 'rgb(0, 120, 255)',
duration: 2000
}).start(color);
В этом случае библиотека сама выполняет цветовую интерполяцию, преобразуя строковые значения в числовое пространство.
При необходимости более тонкого контроля используется функция
transform, позволяющая создавать собственные преобразования
значений.
SVG-градиент состоит из набора stop-точек, каждая из которых имеет позицию и цвет. Эти параметры становятся естественными кандидатами для Popmotion-анимации.
<svg width="0" height="0">
<defs>
<linearGradient id="grad">
<stop id="stop1" offset="0%" stop-color="red" />
<stop id="stop2" offset="100%" stop-color="blue" />
</linearGradient>
</defs>
</svg>
<div id="box"></div>
import { value, tween } from 'popmotion';
const stop1 = document.querySelector('#stop1');
const stop2 = document.querySelector('#stop2');
const colorA = value('rgb(255,0,0)', v => stop1.setAttribute('stop-color', v));
const colorB = value('rgb(0,0,255)', v => stop2.setAttribute('stop-color', v));
tween({
from: 'rgb(255,0,0)',
to: 'rgb(0,200,150)',
duration: 1500
}).start(colorA);
tween({
from: 'rgb(0,0,255)',
to: 'rgb(255,100,0)',
duration: 1500
}).start(colorB);
Такой подход превращает градиент в динамическую систему, где каждая остановка становится независимым анимационным каналом.
Градиент определяется не только цветами, но и направлением. В SVG это
координаты x1, y1, x2,
y2. Их также можно анимировать через Popmotion.
const gradient = document.querySelector('#grad');
const direction = value(
{ x1: 0, y1: 0, x2: 1, y2: 1 },
({ x1, y1, x2, y2 }) => {
gradient.setAttribute('x1', x1);
gradient.setAttribute('y1', y1);
gradient.setAttribute('x2', x2);
gradient.setAttribute('y2', y2);
}
);
tween({
from: { x1: 0, y1: 0, x2: 1, y2: 1 },
to: { x1: 1, y1: 0, x2: 0, y2: 1 },
duration: 3000
}).start(direction);
Изменение геометрии градиента создаёт эффект «перетекания света», который воспринимается как движение источника освещения.
Попmotion интерполирует цвета в разных пространствах. Наиболее предсказуемым для визуальных переходов является HSL, поскольку изменение оттенка происходит линейно.
tween({
from: 'hsl(0, 80%, 50%)',
to: 'hsl(240, 80%, 50%)',
duration: 2500
}).start(v => {
document.body.style.background = v;
});
HSL позволяет избежать грязных переходов, характерных для RGB, особенно при насыщенных цветах.
Паттерн в графике — это регулярная структура, формируемая повторением
элемента. В SVG это <pattern>, в Canvas — тайловая
отрисовка, в DOM — фоновые изображения.
Popmotion здесь используется не для рисования паттерна, а для управления его параметрами:
<svg width="0" height="0">
<defs>
<pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse">
<path d="M 20 0 L 0 0 0 20" fill="none" stroke="black"/>
</pattern>
</defs>
</svg>
<div id="surface"></div>
import { value, tween } from 'popmotion';
const surface = document.querySelector('#surface');
const offset = value(0, v => {
surface.style.backgroundPosition = `${v}px ${v}px`;
});
tween({
from: 0,
to: 100,
duration: 2000,
repeat: Infinity
}).start(offset);
Движение паттерна создаёт эффект «живой поверхности», где статическая сетка воспринимается как поток.
Изменение масштаба повторяющегося узора создаёт визуальный эффект пульсации.
const scale = value(1, v => {
surface.style.transform = `scale(${v})`;
});
tween({
from: 1,
to: 1.2,
duration: 1200,
flip: Infinity
}).start(scale);
При синхронизации с цветом возникает эффект органического движения, где структура и цвет подчинены одной временной кривой.
Градиенты и паттерны раскрываются полностью только при координации нескольких анимационных потоков. Popmotion позволяет запускать параллельные tween’ы, формируя единый временной контур.
import { tween, parallel } from 'popmotion';
parallel([
tween({ from: 0, to: 100, duration: 2000 }),
tween({ from: 1, to: 0.5, duration: 2000 })
]).start(([offset, scale]) => {
surface.style.backgroundPosition = `${offset}px ${offset}px`;
surface.style.transform = `scale(${scale})`;
});
Согласованное движение параметров создаёт ощущение целостного визуального поля, а не набора отдельных эффектов.
Вместо линейных интерполяций применяются пружинные модели, которые дают физически правдоподобное затухание движения.
import { spring, value } from 'popmotion';
const color = value('rgb(255,0,0)', v => {
document.body.style.background = v;
});
spring({
from: 'rgb(255,0,0)',
to: 'rgb(0,150,255)',
stiffness: 120,
damping: 20
}).start(color);
Такая модель особенно эффективна для градиентов, поскольку цветовые переходы начинают вести себя как инерционная система.
Если рассматривать паттерн не как изображение, а как функцию, зависящую от набора переменных, Popmotion превращается в инструмент управления этим полем:
В этом подходе визуальная текстура становится результатом непрерывной математической деформации, а не фиксированного изображения.