Разбиение сложных путей

В библиотеке SVG.js путь (path) представляет собой последовательность команд для построения сложной графики: линии, кривые, дуги, а также их комбинации. Основной объект пути создаётся через метод .path() и принимает строку команд в формате SVG Path Data (M, L, C, Q, A, Z). Пример создания простого пути:

const draw = SVG().addTo('body').size(500, 500);
const path = draw.path('M50 50 L150 50 L150 150 Z');
path.stroke({ width: 2, color: '#000' }).fill('none');

Каждая команда описывает конкретный сегмент пути, что позволяет последовательно разбивать сложные формы на составляющие.


Методы разбивания пути

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

  1. array() Преобразует путь в массив отдельных сегментов. Каждый сегмент представлен как массив: первая позиция — команда, последующие — параметры.
const segments = path.array();
console.log(segments);
/* Вывод:
[
  ['M', 50, 50],
  ['L', 150, 50],
  ['L', 150, 150],
  ['Z']
]
*/
  1. plot() Позволяет как задать, так и получить данные пути. Для разбивки сложного пути удобно сначала получить массив сегментов через array(), модифицировать его и затем применить обратно через plot().
path.plot([['M', 60, 60], ['L', 160, 60], ['L', 160, 160], ['Z']]);
  1. splitAt(length) Делит путь на два пути по заданной длине от начала. Этот метод важен при анимации или при построении интерактивных графиков, где нужно работать с частями пути.
const firstHalf = path.splitAt(100);
const secondHalf = path;

Работа с сегментами

Каждый сегмент пути можно рассматривать как отдельный объект для анализа или модификации. Команды сегментов:

  • M x y — перемещение без рисования
  • L x y — линия до точки
  • H x / V y — горизонтальная/вертикальная линия
  • C x1 y1 x2 y2 x y — кубическая кривизна
  • Q x1 y1 x y — квадратичная кривая
  • A rx ry x-axis-rotation large-arc-flag sweep-flag x y — дуга
  • Z — замыкание пути

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


Примеры комбинирования сегментов

Разделение многоугольника на линии

const poly = draw.path('M100 100 L200 100 L200 200 L100 200 Z');
const segments = poly.array();

segments.forEach((seg, index) => {
  if (seg[0] === 'L') {
    draw.line(segments[index-1][1], segments[index-1][2], seg[1], seg[2])
        .stroke({ width: 2, color: '#f00' });
  }
});

Результат — каждая линия многоугольника визуализируется отдельно.

Разбиение кривой на равные участки

Для кубической кривой можно вычислить длину с помощью метода length() и затем разбить кривую на отрезки через splitAt().

const curve = draw.path('M50 250 C150 100 250 400 350 250');
const totalLength = curve.length();
const part1 = curve.splitAt(totalLength / 2);

Каждая половина кривой становится отдельным объектом для изменения цвета или анимации.


Манипуляция сложными путями

  1. Изменение отдельных сегментов Получив массив сегментов через .array(), можно изменить координаты конкретного сегмента и применить изменения обратно:
let segments = path.array();
segments[1] = ['L', 180, 80]; // изменить вторую линию
path.plot(segments);
  1. Удаление сегментов С помощью массивного подхода легко удалить ненужные сегменты:
segments.splice(2, 1); // удаляем третий сегмент
path.plot(segments);
  1. Создание новых сложных форм Комбинируя сегменты из разных путей, можно строить новые сложные фигуры, сохраняя при этом анимационные возможности SVG.js:
const path1 = draw.path('M10 10 L50 50');
const path2 = draw.path('M50 50 L90 10');
const combined = draw.path([...path1.array(), ...path2.array()]);

Анимация отдельных сегментов

Разделение пути позволяет анимировать сегменты независимо друг от друга. Для линии можно применять метод animate() на каждом сегменте после его выделения через .splitAt() или построения отдельной линии через .line().

segments.forEach(seg => {
  if (seg[0] === 'L') {
    draw.line(seg[1], seg[2], seg[3], seg[4])
        .stroke({ width: 2, color: '#00f' })
        .animate(1000)
        .plot([seg[1], seg[2], seg[3], seg[4]]);
  }
});

Рекомендации по оптимизации

  • Всегда использовать метод array() для сложных форм вместо работы напрямую со строкой пути. Это упрощает анализ и модификацию.
  • Для больших SVG-документов разбиение пути позволяет управлять производительностью, так как можно рендерить только нужные сегменты.
  • Анимацию лучше применять к отдельным сегментам, чтобы избежать полной перерисовки всего пути.

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