SVG.js и React

Для работы с SVG.js в проекте на React достаточно установить библиотеку через npm или yarn:

npm install @svgdotjs/svg.js
# или
yarn add @svgdotjs/svg.js

Импортировать можно как стандартный модуль:

import { SVG } from '@svgdotjs/svg.js';

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

import React, { useRef, useEffect } from 'react';
import { SVG } from '@svgdotjs/svg.js';

function MySVGComponent() {
  const containerRef = useRef(null);

  useEffect(() => {
    const draw = SVG().addTo(containerRef.current).size(300, 300);
    draw.circle(100).fill('red').move(50, 50);
    return () => draw.clear(); // Очистка при размонтировании
  }, []);

  return <div ref={containerRef}></div>;
}

Создание и управление элементами SVG

SVG.js предоставляет интуитивный API для создания и изменения элементов. Основные методы:

  • rect(width, height) — создание прямоугольника
  • circle(radius) — создание круга
  • ellipse(width, height) — создание эллипса
  • line(x1, y1, x2, y2) — создание линии
  • polyline(points) и polygon(points) — создание многоугольников и ломаных линий
  • text(content) — добавление текста

Каждый элемент поддерживает методы для трансформаций и стилей:

const rect = draw.rect(100, 50).fill('#3498db').stroke({ width: 2, color: '#2c3e50' });
rect.move(20, 30).rotate(45, 50, 25); // вращение вокруг центра элемента
rect.animate(1000).move(150, 100);   // анимация перемещения

Работа с группами

Группы позволяют объединять несколько элементов и управлять ими как единым объектом:

const group = draw.group();
group.add(draw.circle(50).fill('green').move(10, 10));
group.add(draw.rect(80, 40).fill('blue').move(60, 20));
group.rotate(30);

Группы особенно полезны при создании сложных интерактивных компонентов в React.

Анимация и взаимодействие

SVG.js поддерживает анимации через метод animate:

circle.animate(2000, '<>').attr({ r: 80, fill: 'orange' });

Параметры:

  • длительность (ms)
  • easing: линейная ('-'), ускорение ('>'), замедление ('<'), комбинации ('<>')
  • target: свойства, которые анимируются

Интерактивность добавляется через стандартные события:

rect.on('click', () => rect.fill({ color: '#e74c3c' }));
rect.on('mouseover', () => rect.opacity(0.7));
rect.on('mouseout', () => rect.opacity(1));

В React важно учитывать синхронизацию с состоянием:

const [color, setColor] = React.useState('blue');

useEffect(() => {
  const rect = draw.rect(100, 50).fill(color);
  rect.on('click', () => setColor(color === 'blue' ? 'red' : 'blue'));
}, [color]);

Работа с компонентами React и SVG.js

Для повторного использования SVG-элементов удобно оборачивать их в отдельные компоненты:

function AnimatedCircle({ radius, color, x, y }) {
  const ref = useRef(null);

  useEffect(() => {
    const draw = SVG().addTo(ref.current).size(200, 200);
    const circle = draw.circle(radius * 2).fill(color).move(x, y);
    circle.animate(1000).attr({ r: radius * 1.5 });
    return () => draw.clear();
  }, [radius, color, x, y]);

  return <div ref={ref}></div>;
}

Такой подход позволяет использовать props для динамических анимаций и стилей, что идеально сочетается с React-паттернами.

Работа с координатами и трансформациями

SVG.js упрощает сложные трансформации:

  • move(x, y) — перемещение
  • center(cx, cy) — установка центра
  • rotate(angle, cx, cy) — вращение
  • scale(sx, sy, cx, cy) — масштабирование
  • skew(xAngle, yAngle) — наклон

Трансформации можно комбинировать:

rect.move(50, 50).rotate(30).scale(1.5, 1.5).skew(10, 0);

Для реактивных интерфейсов в React можно привязывать эти трансформации к состоянию или анимационным библиотекам вроде framer-motion.

Использование внешних данных

SVG.js удобно интегрируется с динамическими данными:

const data = [
  { x: 10, y: 50, r: 20 },
  { x: 70, y: 80, r: 15 },
  { x: 130, y: 40, r: 25 },
];

data.forEach(d => {
  draw.circle(d.r * 2).fill('teal').center(d.x, d.y);
});

Можно создавать графики, диаграммы или интерактивные схемы, комбинируя React state и методы SVG.js.

Работа с текстом и шрифтами

Метод text поддерживает форматирование:

const txt = draw.text('Hello SVG.js')
  .font({ size: 24, family: 'Arial', anchor: 'middle', leading: '1.5em' })
  .move(100, 50);

SVG.js позволяет задавать стили подтекстов, tspan, выравнивание, обрезку текста и цвет.

Экспорт и взаимодействие с DOM

SVG.js работает напрямую с DOM-элементами, что позволяет:

  • Интегрировать с внешними библиотеками (например, D3)
  • Экспортировать SVG как строку или файл:
const svgString = draw.svg(); // получение SVG-кода
  • Применять фильтры и маски:
const filter = draw.filter();
filter.blur(3);
rect.filterWith(filter);

Фильтры создают визуальные эффекты без изменения базовой геометрии.

Оптимизация работы в React

  • Использовать useRef для контейнеров, чтобы избежать лишних рендеров
  • Очищать SVG при размонтировании компонента (draw.clear() или draw.remove())
  • Минимизировать количество анимаций одновременно для производительности
  • При больших графиках использовать группы и nested SVG для управления слоями

Эти принципы позволяют создавать интерактивные и динамические SVG-компоненты, полностью интегрированные с архитектурой React.