SVG-анимации в Popmotion опираются на прямое управление атрибутами и стилями SVG-элементов, где каждая трансформация вычисляется как числовая интерполяция и применяется к DOM без промежуточных абстракций. В отличие от CSS-анимаций, здесь нет скрытого слоя композитинга браузера — каждое изменение координат, трансформаций или параметров пути проходит через JavaScript-функции, что делает поведение полностью предсказуемым и управляемым.
SVG представляет собой декларативную графику, где все элементы описаны через координаты, кривые и атрибуты. Popmotion превращает эти статические значения в динамические, используя функции интерполяции.
Ключевой момент заключается в том, что SVG не требует canvas-перерисовки: достаточно изменять атрибуты DOM-узлов.
Основные типы параметров, которые обычно анимируются:
x, y у примитивовcx, cy у окружностейpoints у polygon и
polylined у pathtranslate, scale,
rotatefill, stroke,
opacityPopmotion работает поверх этих значений, создавая поток изменений, который применяется в каждый кадр анимации.
Popmotion использует концепцию tweening — перехода между двумя состояниями.
import { tween } from 'popmotion';
const element = document.querySelector('circle');
tween({
from: 0,
to: 300,
duration: 1000
}).start(v => {
element.setAttribute('cx', v);
});
В SVG-анимации важно, что любое числовое значение может быть точкой
интерполяции. Однако SVG часто содержит сложные строки, например путь
d, и для них требуется специализированная обработка.
Атрибут d является наиболее сложным элементом
SVG-анимации. Он содержит последовательность команд, описывающих кривые
Безье, линии и дуги.
Popmotion не интерполирует строки напрямую. Используется разбиение пути на числовые сегменты.
Пример подхода:
import { tween } from 'popmotion';
import { interpolate } from 'flubber';
const fromPath = 'M10 10 H 90 V 90 H 10 Z';
const toPath = 'M50 10 H 90 V 90 H 50 Z';
const morph = interpolate(fromPath, toPath);
tween({
duration: 800
}).start(v => {
const path = morph(v);
document.querySelector('path').setAttribute('d', path);
});
Ключевая особенность SVG-анимации через Popmotion — разделение логики морфинга и тайминга. Popmotion отвечает только за прогресс, а трансформация формы вынесена отдельно.
SVG-элементы часто анимируются не только линейно, но и с физическим поведением. Popmotion позволяет использовать spring-модели, что особенно важно для интерактивных SVG-интерфейсов.
import { spring } from 'popmotion';
const circle = document.querySelector('circle');
spring({
from: 50,
to: 300,
stiffness: 200,
damping: 15
}).start(v => {
circle.setAttribute('cx', v);
});
Физическая модель добавляет инерцию и реалистичное затухание, что делает SVG-объекты визуально “живыми” без ручной настройки ключевых кадров.
SVG поддерживает атрибут transform, который включает
несколько подтипов трансформаций. Popmotion позволяет работать с ними
как с независимыми каналами.
import { tween } from 'popmotion';
const rect = document.querySelector('rect');
tween({
from: 0,
to: 200,
duration: 600
}).start(v => {
rect.setAttribute('transform', `translate(${v}, 0)`);
});
При необходимости несколько трансформаций объединяются вручную:
.start(v => {
rect.setAttribute(
'transform',
`translate(${v}, 0) rotate(${v / 2}) scale(${1 + v / 500})`
);
});
Особенность SVG заключается в порядке применения трансформаций: rotate после translate даёт другой результат, чем translate после rotate. Popmotion не скрывает эту сложность, оставляя контроль на уровне разработчика.
SVG часто состоит из групп элементов (<g>),
которые должны анимироваться синхронно. Popmotion решает это через
параллельные потоки.
import { tween, parallel } from 'popmotion';
const circle = document.querySelector('circle');
const rect = document.querySelector('rect');
parallel([
tween({ from: 0, to: 100, duration: 800 }),
tween({ from: 100, to: 0, duration: 800 })
]).start(([c, r]) => {
circle.setAttribute('cy', c);
rect.setAttribute('x', r);
});
SVG-структура при этом остаётся статической, изменяются только вычисленные значения.
<g> и наследованием трансформацийГруппировка элементов позволяет применять единые трансформации к множеству объектов.
const group = document.querySelector('g');
tween({
from: 0,
to: 360,
duration: 1200
}).start(v => {
group.setAttribute('transform', `rotate(${v} 100 100)`);
});
SVG наследует трансформации вниз по дереву, что снижает нагрузку на отдельные элементы и повышает производительность.
SVG-анимации в Popmotion тесно связаны с системой координат. Атрибут
viewBox определяет масштаб и интерпретацию всех
значений.
Изменение viewBox само по себе может быть анимируемым
параметром:
tween({
from: 0,
to: 50,
duration: 1000
}).start(v => {
svg.setAttribute('viewBox', `${v} ${v} 200 200`);
});
Такой подход позволяет создавать эффекты зума и панорамирования без изменения отдельных элементов.
SVG-анимация через Popmotion зависит от количества DOM-операций. Основные факторы влияния:
Оптимизация часто сводится к уменьшению количества операций
setAttribute и агрегации изменений.
Пример оптимизированного подхода:
let x = 0;
let y = 0;
tween({
from: 0,
to: 1,
duration: 1000
}).start(v => {
x = 100 * v;
y = 200 * (1 - v);
element.setAttribute('transform', `translate(${x}, ${y})`);
});
Здесь используется одно обновление вместо нескольких отдельных вызовов.
SVG-анимации часто связаны с пользовательскими событиями. Popmotion интегрируется через запуск анимаций по триггерам.
const circle = document.querySelector('circle');
circle.addEventListener('mouseenter', () => {
tween({
from: 50,
to: 120,
duration: 300
}).start(v => {
circle.setAttribute('r', v);
});
});
SVG сохраняет свою семантическую структуру, а интерактивность добавляется поверх.
Сложные SVG-анимации часто требуют преобразования геометрии между несовместимыми фигурами. Popmotion используется только как тайминг-движок, а геометрическая интерполяция выполняется отдельно.
Подход с нормализацией путей:
Это позволяет создавать переходы между любыми SVG-формами, включая логотипы, иконки и абстрактные фигуры.
SVG часто используется вместе с HTML-элементами. Popmotion позволяет синхронизировать анимации разных типов DOM.
import { tween, all } from 'popmotion';
all([
tween({ from: 0, to: 300, duration: 1000 }),
tween({ from: 1, to: 0, duration: 1000 })
]).start(([pos, opacity]) => {
circle.setAttribute('cx', pos);
panel.style.opacity = opacity;
});
SVG в этом контексте становится частью общей анимационной сцены, а не изолированным графическим слоем.