Градиенты и паттерны

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

Цвет в анимации нельзя рассматривать как строку. Он раскладывается на компоненты: RGB, HSL или HSV. Popmotion оперирует числовыми значениями, поэтому любой градиент фактически сводится к набору анимируемых чисел.

Базовая идея:

  • цвет → числовой вектор
  • вектор → интерполяция
  • интерполяция → обновление DOM / SVG / Canvas

Интерполяция цвета через value и transform

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 как система анимируемых остановок

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-паттерна через смещение

<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})`;
});

Согласованное движение параметров создаёт ощущение целостного визуального поля, а не набора отдельных эффектов.


Использование spring-модели для естественных переходов

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

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 превращается в инструмент управления этим полем:

  • координаты → смещение
  • время → фаза
  • амплитуда → масштаб
  • цвет → значение функции

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