Анимация SVG-элементов

SVG (Scalable Vector Graphics) представляет собой XML-основанную модель описания векторной графики, где каждый элемент — это DOM-узел, доступный для манипуляции через JavaScript. Именно это делает SVG особенно удобным для анимации в связке с Velocity.js, поскольку библиотека работает напрямую с DOM-элементами и их атрибутами.

Velocity.js поддерживает анимацию как стандартных CSS-свойств, так и SVG-атрибутов, включая трансформации, геометрические параметры и специфические свойства вроде stroke-dashoffset. Это позволяет строить сложные визуальные эффекты без использования Canvas или WebGL.


Базовые принципы работы SVG в DOM

SVG-элементы встраиваются в DOM как полноценные узлы, например:

<svg width="200" height="200">
  <circle cx="100" cy="100" r="50" fill="transparent" stroke="black" />
</svg>

Каждый атрибут (cx, cy, r, stroke) может быть изменён через JavaScript. Velocity.js использует этот факт и расширяет возможности анимации за счёт интерполяции числовых значений.

Особенность SVG-анимации заключается в том, что:

  • геометрические атрибуты анимируются как числа;
  • цвета интерполируются в RGB;
  • трансформации применяются через transform атрибут;
  • некоторые свойства требуют явного указания единиц измерения.

Подключение Velocity.js к SVG-элементам

Velocity.js работает с SVG-элементами без дополнительных адаптеров. Элемент передаётся напрямую:

Velocity(document.querySelector("circle"), {
  r: 80
}, {
  duration: 1000
});

Изменение радиуса круга происходит плавно, поскольку Velocity интерполирует числовое значение r.

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


Анимация базовых геометрических атрибутов

Радиус и координаты

Наиболее простые случаи включают изменение координат и размеров:

Velocity(document.querySelector("circle"), {
  cx: 150,
  cy: 150,
  r: 30
}, {
  duration: 800,
  easing: "easeInOutQuad"
});

Такая анимация приводит к перемещению и изменению формы круга.


Прямоугольники

Velocity(document.querySelector("rect"), {
  width: 180,
  height: 80,
  x: 20,
  y: 40
}, {
  duration: 1200
});

SVG-атрибуты x, y, width, height интерполируются как обычные числа, что позволяет создавать эффект растяжения или перемещения блока.


Работа с transform в SVG

SVG использует собственную систему трансформаций, отличную от CSS, но Velocity.js унифицирует подход.

Velocity(document.querySelector("g"), {
  translateX: 100,
  translateY: 50,
  rotateZ: 45,
  scale: 1.5
}, {
  duration: 1000
});

Группы <g> особенно удобны для анимации, поскольку позволяют перемещать сразу несколько элементов как единое целое.

Особенности:

  • translateX/Y интерпретируются в координатах SVG;
  • rotateZ вращает вокруг точки трансформации;
  • scale изменяет размер относительно центра или заданной точки.

Анимация контуров через stroke-dasharray

Одним из наиболее выразительных эффектов SVG является “прорисовка линии”. Он достигается через свойства stroke-dasharray и stroke-dashoffset.

Принцип:

  • создаётся пунктирная линия, покрывающая весь путь;
  • смещение stroke-dashoffset скрывает или показывает контур.
<svg width="300" height="150">
  <path d="M10 80 Q 95 10 180 80 T 330 80"
        stroke="black"
        fill="transparent"
        stroke-width="2"/>
</svg>
const path = document.querySelector("path");
const length = path.getTotalLength();

path.style.strokeDasharray = length;
path.style.strokeDashoffset = length;

Velocity(path, {
  strokeDashoffset: 0
}, {
  duration: 2000,
  easing: "linear"
});

Такой подход создаёт эффект постепенного рисования линии.


Анимация пути и сложных форм

Velocity.js не выполняет морфинг SVG-path напрямую, но можно анимировать отдельные параметры или использовать промежуточные состояния.

Для частичной имитации морфинга применяется:

  • замена d атрибута;
  • синхронная интерполяция нескольких path;
  • библиотечные расширения.

Пример простой смены формы:

Velocity(document.querySelector("path"), {
  d: "M10 10 L200 10 L200 200 L10 200 Z"
}, {
  duration: 1500
});

Поддержка зависит от браузера и структуры пути. Более стабильный подход — использование заранее совместимых path.


Цветовые анимации SVG

Velocity.js интерполирует цвета в формате RGB:

Velocity(document.querySelector("circle"), {
  fill: "#ff0000",
  stroke: "#0000ff"
}, {
  duration: 1000
});

Также поддерживаются rgba-значения:

Velocity(element, {
  fill: "rgba(0, 200, 100, 0.8)"
});

Особенность SVG заключается в том, что fill и stroke являются атрибутами, а не CSS-свойствами, хотя современные браузеры позволяют работать с ними как с CSS.


Групповая анимация SVG-элементов

SVG часто содержит сложную иерархию элементов:

<svg>
  <g class="group">
    <circle cx="50" cy="50" r="20"/>
    <rect x="100" y="40" width="40" height="40"/>
  </g>
</svg>

Velocity.js позволяет анимировать всю группу:

Velocity(document.querySelector(".group"), {
  translateX: 120,
  rotateZ: 30,
  scale: 1.2
}, {
  duration: 900
});

Групповая анимация снижает количество вызовов рендеринга и повышает производительность.


Последовательные и параллельные SVG-анимации

Velocity.js поддерживает цепочки анимаций:

Velocity(circle, { r: 60 }, { duration: 500 })
  .then(() => Velocity(circle, { fill: "#00ff00" }, { duration: 500 }))
  .then(() => Velocity(circle, { cx: 200 }, { duration: 500 }));

Также возможно одновременное выполнение нескольких эффектов:

Velocity(circle, {
  r: 80,
  cx: 150,
  fill: "#ffcc00"
}, {
  duration: 1200
});

Производительность SVG-анимаций

SVG-анимация в Velocity.js опирается на DOM, поэтому производительность зависит от количества элементов и частоты обновлений.

Ключевые факторы оптимизации:

  • минимизация количества одновременно анимируемых узлов;
  • использование <g> для группировки;
  • избегание анимации сложных path в реальном времени;
  • предпочтение transform вместо геометрических изменений.

Transform-операции обрабатываются GPU-ускорением, что делает их значительно быстрее.


Типовые ошибки при анимации SVG

Часто встречающиеся проблемы:

1. Анимация строковых атрибутов

Некоторые атрибуты не являются числовыми и не интерполируются.

2. Отсутствие единиц измерения

SVG требует строгого соответствия типов данных.

3. Попытка анимации неподдерживаемых свойств

Не все SVG-атрибуты доступны для интерполяции через Velocity.

4. Прямое изменение DOM без учета состояния Velocity

Может приводить к рывкам и сбросу анимации.


Композиция сложных SVG-сцен

Сложные сцены обычно строятся как комбинация:

  • трансформаций групп;
  • анимации отдельных элементов;
  • эффекта рисования контуров;
  • цветовых переходов.

Пример композиции:

Velocity(group, { translateX: 100 }, { duration: 800 });

Velocity(path, {
  strokeDashoffset: 0
}, {
  duration: 1500
});

Velocity(circle, {
  r: 40,
  fill: "#3498db"
}, {
  duration: 1000
});

Синхронизация достигается либо таймингами, либо цепочками промисов.


Использование easing-функций в SVG-анимации

Velocity.js предоставляет набор easing-функций, влияющих на характер движения:

Velocity(circle, {
  cy: 200
}, {
  duration: 1200,
  easing: "easeInOutCubic"
});

Easing особенно заметен при трансформациях и изменении формы, создавая физически правдоподобное движение элементов SVG-сцены.