SVG использует декларативную модель, где внешний вид графики задаётся через набор атрибутов элементов: координаты, радиусы, параметры пути, трансформации и стили. Эти атрибуты могут быть статичными, но в сочетании с Popmotion становятся динамическими значениями, изменяющимися во времени под управлением анимационных функций.
SVG-элементы описываются через набор числовых и строковых атрибутов:
x, y, cx,
cy, r, width,
heightdfill, stroke,
stroke-widthopacity,
visibilitytransformОсобенность SVG заключается в том, что многие из этих атрибутов напрямую влияют на отрисовку и могут изменяться без перерасчёта DOM-структуры. Это делает их удобной целью для анимации.
Popmotion работает с такими значениями как с потоками данных,
обновляя их на каждом кадре через
requestAnimationFrame.
Основной механизм взаимодействия Popmotion с DOM и SVG —
styler. Он создаёт абстракцию над элементом, позволяя
задавать свойства без ручного вызова setAttribute.
import { styler, tween } from 'popmotion';
const circle = document.querySelector('circle');
const circleStyler = styler(circle);
После этого любые изменения координат или атрибутов можно задавать напрямую:
circleStyler.set({ cx: 50, cy: 50, r: 20 });
Popmotion автоматически определяет, какие свойства относятся к SVG и корректно применяет их через атрибуты элемента, а не через CSS.
Ключевая особенность: styler синхронизирует состояние объекта и DOM без ручного управления атрибутами.
Наиболее частый сценарий — анимация координат и размеров SVG-элементов.
import { animate, styler } from 'popmotion';
const circle = document.querySelector('circle');
const circleStyler = styler(circle);
animate({
from: { cx: 50, cy: 50 },
to: { cx: 300, cy: 200 },
duration: 1000,
onUpdate: v => circleStyler.set(v)
});
В этом примере изменяются атрибуты cx и cy,
определяющие положение круга.
animate({
from: { r: 10 },
to: { r: 80 },
duration: 600,
onUpdate: v => circleStyler.set(v)
});
Изменение радиуса приводит к перерасчёту формы элемента без необходимости перерисовки всей сцены.
Popmotion использует встроенные интерполяторы, которые автоматически определяют тип данных:
animate({
from: { opacity: 0 },
to: { opacity: 1 },
duration: 400,
onUpdate: v => circleStyler.set(v)
});
Даже такие атрибуты, как stroke-width, могут участвовать
в анимации без дополнительной обработки.
SVG-примитивы имеют набор специфичных атрибутов:
rect: x, y,
width, height, rx,
ryline: x1, y1,
x2, y2Popmotion позволяет изменять их так же, как и координаты.
const rect = document.querySelector('rect');
const rectStyler = styler(rect);
animate({
from: { width: 50, height: 50 },
to: { width: 200, height: 120 },
duration: 800,
onUpdate: v => rectStyler.set(v)
});
Изменение размеров происходит плавно, без необходимости вручную пересчитывать позиции.
Пути SVG (<path>) — наиболее гибкий, но и сложный
тип элемента. Их атрибут d представляет собой строку
команд, описывающих кривые и линии.
Popmotion напрямую не интерполирует строки d, но
используется популярный подход через свойства обводки:
stroke-dasharraystroke-dashoffsetconst path = document.querySelector('path');
const pathStyler = styler(path);
const length = path.getTotalLength();
pathStyler.set({
strokeDasharray: length,
strokeDashoffset: length
});
animate({
from: { progress: length },
to: { progress: 0 },
duration: 2000,
onUpdate: v => pathStyler.set({
strokeDashoffset: v.progress
})
});
Так создаётся эффект постепенного прорисовывания линии.
SVG поддерживает трансформации через атрибут transform,
который может включать:
translatescalerotatePopmotion часто использует трансформации вместо прямого изменения координат, так как это дешевле для рендеринга.
animate({
from: { x: 0 },
to: { x: 300 },
duration: 1000,
onUpdate: v => {
circleStyler.set({
x: v.x
});
}
});
Однако более производительный подход — использование transform-объекта:
circleStyler.set({
translateX: 0
});
animate({
from: 0,
to: 300,
onUpdate: v => {
circleStyler.set({
translateX: v
});
}
});
Popmotion позволяет одновременно управлять множеством свойств SVG, что даёт возможность создавать сложные анимационные сцены.
animate({
from: {
cx: 50,
cy: 50,
r: 10,
opacity: 0
},
to: {
cx: 250,
cy: 150,
r: 60,
opacity: 1
},
duration: 1200,
onUpdate: v => circleStyler.set(v)
});
Такая структура делает анимацию декларативной: состояние описывает не шаги, а конечные значения.
Popmotion позволяет синхронизировать несколько независимых стилизаций через общий источник значений.
const box = styler(document.querySelector('rect'));
const dot = styler(document.querySelector('circle'));
animate({
from: 0,
to: 1,
duration: 1000,
onUpdate: v => {
box.set({ opacity: v });
dot.set({ opacity: 1 - v });
}
});
Таким образом формируется связанная анимация без отдельного таймера для каждого элемента.
SVG допускает отсутствие единиц измерения для большинства числовых атрибутов. Это упрощает интерполяцию:
cx="100" интерпретируется как числовое значениеЕсли используются единицы (px, %),
Popmotion применяет внутренние преобразования, но в SVG это встречается
реже, чем в CSS.
SVG-анимации через Popmotion опираются на следующие принципы:
requestAnimationFrameНа практике наиболее затратными являются:
d у pathfilter,
feGaussianBlur)Оптимизация достигается разбиением анимации на независимые потоки значений.
После завершения animate Popmotion фиксирует конечное
состояние. SVG-элементы сохраняют итоговые атрибуты без дополнительного
вмешательства.
animate({
from: { r: 10 },
to: { r: 50 },
duration: 500,
onUpdate: v => circleStyler.set(v)
});
После завершения r остаётся равным 50, и
элемент сохраняет финальную форму.
SVG-атрибуты удобно рассматривать как реактивные переменные. Popmotion превращает их в поток значений, который обновляется с высокой частотой.
Каждое значение:
Это делает SVG-элементы аналогами визуальных реактивных сущностей, где изменение состояния напрямую отражается в графике без промежуточных слоёв управления.