В Two.js объекты Path используются для
построения сложных форм с помощью линий и кривых. Каждый путь состоит из
массива вершин (vertices), которые задают
ключевые точки фигуры. Основные типы вершин:
Two.Anchor – определяет точку с координатами
(x, y) и опциональными управляющими кривыми
controlLeft и controlRight.Path может быть замкнутым
(closed) или открытым.Пример создания пути:
const path = two.makePath(
50, 50,
150, 50,
150, 150,
50, 150,
true // замкнутый путь
);
path.stroke = '#ff0000';
path.linewidth = 2;
Здесь вершины формируют квадрат. Параметр true закрывает
путь, соединяя последнюю вершину с первой.
Интерполяция позволяет плавно изменять одну форму в другую. Для этого важно, чтобы:
Создание интерполяции выполняется с помощью метода
vertices и циклического обновления координат:
const pathA = two.makePath(50,50, 150,50, 150,150, 50,150, true);
const pathB = two.makePath(100,100, 200,50, 200,200, 100,250, true);
two.bind('upd ate', function(frameCount) {
const t = (Math.sin(frameCount * 0.05) + 1) / 2; // значение от 0 до 1
for (let i = 0; i < pathA.vertices.length; i++) {
pathA.vertices[i].x = pathA.vertices[i].x * (1 - t) + pathB.vertices[i].x * t;
pathA.vertices[i].y = pathA.vertices[i].y * (1 - t) + pathB.vertices[i].y * t;
}
}).play();
Здесь используется линейная интерполяция (LERP) для
координат каждой вершины. Параметр t изменяется во времени,
создавая плавное превращение одной формы в другую.
Если путь содержит кривые, нужно учитывать управляющие
точки controlLeft и controlRight. Для
плавной трансформации кривых они интерполируются так же, как и основные
координаты вершины:
pathA.vertices[i].controlLeft.x = pathA.vertices[i].controlLeft.x * (1 - t) + pathB.vertices[i].controlLeft.x * t;
pathA.vertices[i].controlLeft.y = pathA.vertices[i].controlLeft.y * (1 - t) + pathB.vertices[i].controlLeft.y * t;
pathA.vertices[i].controlRight.x = pathA.vertices[i].controlRight.x * (1 - t) + pathB.vertices[i].controlRight.x * t;
pathA.vertices[i].controlRight.y = pathA.vertices[i].controlRight.y * (1 - t) + pathB.vertices[i].controlRight.y * t;
Это позволяет кривым плавно деформироваться вместе с изменением основной формы.
Перед анимацией часто требуется унифицировать размеры и
положение обеих фигур, чтобы трансформация выглядела корректно.
Используются свойства translation, scale,
rotation:
pathA.translation.se t(100, 100);
pathB.translation.set(100, 100);
pathA.scale = 1;
pathB.scale = 1;
Для сложных анимаций можно использовать Two.Group для
объединения нескольких путей и применения трансформаций к группе
целиком.
Math.sin,
Math.cos, Math.pow.t = (Math.sin(frameCount * factor) + 1) / 2.Пример морфинга сложного объекта:
const star = two.makeStar(200, 200, 50, 100, 5);
const flower = two.makePolygon(200, 200, 80, 6);
two.bind('update', function(frameCount) {
const t = (Math.sin(frameCount * 0.03) + 1) / 2;
for (let i = 0; i < star.vertices.length; i++) {
star.vertices[i].x = star.vertices[i].x * (1 - t) + flower.vertices[i].x * t;
star.vertices[i].y = star.vertices[i].y * (1 - t) + flower.vertices[i].y * t;
}
}).play();
t заранее и обновлять координаты только при
изменении t.Эти подходы позволяют создавать сложные, динамические морфинги форм, плавно превращая одну фигуру в другую в Two.js, сохраняя контроль над кривыми, масштабом и позицией объектов.