Для работы с Two.js необходимо создать экземпляр библиотеки и
привязать его к контейнеру на странице. Основной объект Two
управляет сценой, элементами и рендерингом:
const elem = document.getElementById('draw-area');
const two = new Two({
width: 800,
height: 600,
type: Two.Types.svg // поддержка SVG или Canvas
}).appendTo(elem);
Two.Types позволяет выбрать между svg и
canvas, что влияет на производительность и возможности
анимации. После инициализации создается пространство для отрисовки фигур
и линий.
В Two.js путь (Two.Path) — это последовательность
векторов, соединенных линиями или кривыми. Основная структура пути:
const path = new Two.Path([
new Two.Anchor(100, 100),
new Two.Anchor(200, 150),
new Two.Anchor(150, 250)
], false, false);
two.add(path);
Аргументы конструктора:
Anchor — точки пути. Каждая
точка может иметь контрольные точки для кривых Безье.closed — булевое значение, замкнут
путь или нет.curved — определяет, будут ли линии
между точками кривыми.Каждый путь содержит массив vertices, который хранит
объекты Vector. Длина пути вычисляется через
последовательное суммирование длин сегментов между точками:
path.vertices.forEach((vertex, i, vertices) => {
if (i > 0) {
const prev = vertices[i - 1];
const dx = vertex.x - prev.x;
const dy = vertex.y - prev.y;
const segmentLength = Math.sqrt(dx * dx + dy * dy);
console.log(`Длина сегмента ${i}: ${segmentLength}`);
}
});
dx и dy — смещения по
осям X и Y.Math.sqrt(dx*dx + dy*dy) — стандартная
формула Евклидовой длины линии.Чтобы получить суммарную длину всего пути, необходимо пройти по всем сегментам и сложить их длины:
function getPathLength(path) {
let totalLength = 0;
const vertices = path.vertices;
for (let i = 1; i < vertices.length; i++) {
const dx = vertices[i].x - vertices[i - 1].x;
const dy = vertices[i].y - vertices[i - 1].y;
totalLength += Math.sqrt(dx * dx + dy * dy);
}
if (path.closed) {
const dx = vertices[0].x - vertices[vertices.length - 1].x;
const dy = vertices[0].y - vertices[vertices.length - 1].y;
totalLength += Math.sqrt(dx * dx + dy * dy);
}
return totalLength;
}
console.log("Общая длина пути:", getPathLength(path));
Особенности:
closed = true), нужно добавить длину
сегмента между последней и первой точкой.Кривые Безье в Two.js хранятся как anchor.controls.left
и anchor.controls.right. Для вычисления длины кривой
применяется разбиение на N отрезков:
function bezierLength(anchor1, anchor2, steps = 100) {
let length = 0;
let prev = anchor1;
for (let i = 1; i <= steps; i++) {
const t = i / steps;
const x = Math.pow(1 - t, 3) * anchor1.x +
3 * Math.pow(1 - t, 2) * t * (anchor1.x + anchor1.controls.right.x) +
3 * (1 - t) * t * t * (anchor2.x + anchor2.controls.left.x) +
t * t * t * anchor2.x;
const y = Math.pow(1 - t, 3) * anchor1.y +
3 * Math.pow(1 - t, 2) * t * (anchor1.y + anchor1.controls.right.y) +
3 * (1 - t) * t * t * (anchor2.y + anchor2.controls.left.y) +
t * t * t * anchor2.y;
const dx = x - prev.x;
const dy = y - prev.y;
length += Math.sqrt(dx * dx + dy * dy);
prev = { x, y };
}
return length;
}
steps — количество разбиений кривой,
большее число дает точнее длину.Для суммарной длины пути с кривыми:
function getFullPathLength(path) {
let total = 0;
const vertices = path.vertices;
for (let i = 1; i < vertices.length; i++) {
if (path.curved) {
total += bezierLength(vertices[i - 1], vertices[i]);
} else {
const dx = vertices[i].x - vertices[i - 1].x;
const dy = vertices[i].y - vertices[i - 1].y;
total += Math.sqrt(dx * dx + dy * dy);
}
}
if (path.closed) {
if (path.curved) {
total += bezierLength(vertices[vertices.length - 1], vertices[0]);
} else {
const dx = vertices[0].x - vertices[vertices.length - 1].x;
const dy = vertices[0].y - vertices[vertices.length - 1].y;
total += Math.sqrt(dx * dx + dy * dy);
}
}
return total;
}
console.log("Длина пути с кривыми:", getFullPathLength(path));