Длина пути и позиция на пути

В SVG.js каждый элемент <path> обладает свойством, позволяющим получить длину пути. Это особенно полезно для анимаций, рисования линий «поэтапно» и определения положения объектов на кривых.

const draw = SVG().addTo('body').size(600, 400);
const path = draw.path('M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80');

// Получение полной длины пути
const totalLength = path.length();
console.log(totalLength);

Метод length() возвращает длину пути в пикселях. Для сложных кривых длина вычисляется с учётом всех сегментов (линии, квадратичные и кубические кривые Безье, дуги).

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

  • Длина пересчитывается автоматически при изменении атрибутов d.
  • Используется в анимациях для эффекта «рисования линии».
  • Для прямых линий длина совпадает с обычным расстоянием между точками.

Определение точки на пути

Метод pointAt() позволяет определить координаты точки на пути по заданной длине от начала.

const point = path.pointAt(50); // точка на 50px от начала пути
console.log(point.x, point.y);

Ключевые моменты:

  • Аргумент метода — длина пути в пикселях.
  • Возвращает объект {x, y}.
  • Позволяет точно размещать объекты вдоль кривой, синхронизируя движение с анимацией.

Использование атрибута path.get() для доступа к сегментам

Метод array() возвращает массив сегментов пути, что позволяет анализировать структуру:

const segments = path.array();
segments.forEach(seg => console.log(seg));

Пример сегмента: ['M', 10, 80] — перемещение без рисования, ['C', 40, 10, 65, 10, 95, 80] — кубическая кривая Безье.

Это важно для динамического расчета длины отдельных сегментов или вычисления точек на сложных кривых.


Анимация по длине пути

SVG.js позволяет создавать эффект «рисования линии», используя длину пути и атрибут stroke-dasharray:

const length = path.length();
path.stroke({ width: 2, color: '#000' })
    .attr({ 'stroke-dasharray': length, 'stroke-dashoffset': length })
    .animate(2000)
    .attr({ 'stroke-dashoffset': 0 });

Объяснение:

  • stroke-dasharray задаёт длину штрихов, равную длине всего пути.
  • stroke-dashoffset управляет смещением штрихов, что создаёт иллюзию постепенного рисования линии.
  • Анимация с attr() постепенно уменьшает stroke-dashoffset до 0, визуально «отрисовывая» путь.

Определение положения объекта на кривой

Можно перемещать объект вдоль пути с использованием pointAt():

const circle = draw.circle(10).fill('red');

let distance = 0;
const speed = 2; // пикселей за кадр

SVG.animate(function(){
  distance += speed;
  if(distance > path.length()) distance = 0;
  const { x, y } = path.pointAt(distance);
  circle.center(x, y);
});

Особенности реализации:

  • Можно реализовать бесконечное движение по замкнутому пути.
  • Позволяет синхронизировать объекты с анимацией пути (например, точки движения, машинки, шарики).

Разделение пути на сегменты по длине

SVG.js не предоставляет прямого метода «разделить по длине», но можно вычислять точки на пути и строить новые сегменты:

const segmentLength = 20;
for(let i = 0; i <= path.length(); i += segmentLength){
  const { x, y } = path.pointAt(i);
  draw.circle(2).fill('blue').center(x, y);
}

Это позволяет:

  • Визуализировать путь точками через равные интервалы.
  • Создавать кастомные анимации или эффекты «шагающих объектов».

Комбинация с другими элементами SVG

Положение на пути часто комбинируется с трансформациями:

const rect = draw.rect(20, 10).fill('green');
const rotationOffset = 0.1; // радианы

const { x, y } = path.pointAt(100);
const tangent = path.tangentAt(100); // метод tangentAt() возвращает угол касательной
rect.center(x, y).rotate(tangent * 180 / Math.PI);
  • tangentAt() вычисляет угол касательной к пути в заданной точке.
  • Позволяет «ориентировать» объекты по кривой, что полезно для анимации транспорта или стрелок вдоль пути.

Практические советы

  • Для точного расчета используйте дробные значения длины пути.
  • Для сложных кривых Безье длина может изменяться при редактировании пути, поэтому лучше пересчитывать перед каждой анимацией.
  • Для замкнутых путей (Z) длина учитывает соединение последней и первой точки.
  • Комбинация length() + pointAt() + tangentAt() даёт полный контроль над объектами вдоль кривой.

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