Манипуляция якорными точками

Якорные точки (anchors) — базовые элементы, определяющие форму кривых и сложных фигур в Two.js. Каждая точка хранит координаты и дополнительные параметры, влияющие на кривизну сегментов. В основе лежит использование кубических кривых Безье, где каждая точка может иметь управляющие векторы (handles), задающие направление входа и выхода линии.

Объект якорной точки представлен классом Two.Anchor, который включает:

  • x, y — координаты точки
  • controls.left — управляющая точка для входящей кривой
  • controls.right — управляющая точка для исходящей кривой
  • command — тип сегмента (move, line, curve, close)

Структура Anchor

const anchor = new Two.Anchor(100, 100);

Расширенный вариант с управляющими точками:

const anchor = new Two.Anchor(
  100, 100,
  50, 50,    // left control
  150, 150,  // right control
  Two.Commands.curve
);

Ключевые свойства:

  • anchor.x, anchor.y
  • anchor.controls.left.x, anchor.controls.left.y
  • anchor.controls.right.x, anchor.controls.right.y

Типы сегментов

Каждая якорная точка определяет, как соединяется с предыдущей:

  • Two.Commands.move — перемещение без рисования
  • Two.Commands.line — прямая линия
  • Two.Commands.curve — кривая Безье
  • Two.Commands.close — замыкание пути

Пример:

anchor.command = Two.Commands.line;

Работа с управляющими точками

Управляющие точки определяют форму кривой между двумя якорями.

Левая управляющая точка влияет на входящую кривую Правая управляющая точка — на исходящую

anchor.controls.left.set(-20, 0);
anchor.controls.right.set(20, 0);

Смещение происходит относительно самой якорной точки.

Включение и отключение кривизны

Для преобразования кривой в прямую линию:

anchor.command = Two.Commands.line;

Для возврата кривизны:

anchor.command = Two.Commands.curve;

Удаление управляющих точек:

anchor.controls.left.clear();
anchor.controls.right.clear();

Создание пользовательских путей

Путь (Two.Path) строится из массива якорных точек:

const path = new Two.Path([
  new Two.Anchor(0, 0),
  new Two.Anchor(100, 0),
  new Two.Anchor(100, 100),
  new Two.Anchor(0, 100)
], true);

Замкнутый путь задаётся вторым аргументом true.

Динамическое изменение якорей

Изменение координат:

anchor.x = 200;
anchor.y = 150;

Изменение управляющих точек:

anchor.controls.right.x = 30;
anchor.controls.right.y = 10;

После изменения сцена автоматически обновляется при следующем рендере.

Добавление и удаление точек

Добавление:

path.vertices.push(new Two.Anchor(150, 150));

Удаление:

path.vertices.splice(index, 1);

После изменения массива вершин необходимо обновить флаг:

path._flagVertices = true;

Интерполяция между якорями

Для плавных анимаций часто используется интерполяция:

anchor.x += (targetX - anchor.x) * 0.1;
anchor.y += (targetY - anchor.y) * 0.1;

Управляющие точки также можно интерполировать для сохранения формы кривой.

Симметричные управляющие точки

Для плавных кривых часто требуется зеркальность:

anchor.controls.left.x = -anchor.controls.right.x;
anchor.controls.left.y = -anchor.controls.right.y;

Это создаёт гладкие переходы без резких изломов.

Автоматическое сглаживание

Two.js поддерживает режим автоматического сглаживания:

path.curved = true;

Библиотека самостоятельно рассчитывает управляющие точки.

Ручное сглаживание

При отключённом curved требуется вручную задавать контроллеры:

path.curved = false;

И затем:

anchor.controls.left.set(-10, -10);
anchor.controls.right.set(10, 10);

Работа с замкнутыми контурами

В замкнутом пути первая и последняя точки соединяются:

path.closed = true;

Управляющие точки крайних вершин влияют друг на друга, формируя непрерывную кривую.

Индексация и доступ

Доступ к якорям:

const first = path.vertices[0];

Перебор:

path.vertices.forEach(anchor => {
  anchor.x += 1;
});

Реактивность изменений

Two.js использует флаги для отслеживания изменений:

  • _flagVertices
  • _flagControls

Принудительное обновление:

path._flagVertices = true;

Анимация формы

Пример деформации фигуры:

two.bind('upd ate', function() {
  path.vertices.forEach((anchor, i) => {
    anchor.y += Math.sin(i + Date.now() * 0.002);
  });
});

Создание сложных кривых

Комбинирование сегментов:

const anchors = [
  new Two.Anchor(0, 0),
  new Two.Anchor(50, 100, 30, 0, -30, 0, Two.Commands.curve),
  new Two.Anchor(100, 0)
];

const path = new Two.Path(anchors, false);

Манипуляция через математику

Изменение формы по синусоиде:

anchor.x += Math.cos(time) * 5;
anchor.y += Math.sin(time) * 5;

Поворот вокруг точки:

const dx = anchor.x - cx;
const dy = anchor.y - cy;

anchor.x = cx + dx * Math.cos(angle) - dy * Math.sin(angle);
anchor.y = cy + dx * Math.sin(angle) + dy * Math.cos(angle);

Работа с относительными координатами

Управляющие точки задаются относительно якоря, что важно учитывать при трансформациях:

anchor.controls.left.se t(-anchor.controls.right.x, -anchor.controls.right.y);

Распространённые ошибки

  • Отсутствие обновления _flagVertices
  • Неправильное понимание относительности управляющих точек
  • Смешивание line и curve без контроля переходов
  • Использование curved = true вместе с ручными контроллерами

Практика: деформируемая фигура

const path = two.makePath(0, 0, 100, 0, 100, 100, 0, 100, true);

two.bind('update', () => {
  path.vertices.forEach((anchor, i) => {
    anchor.x += Math.sin(i + performance.now() * 0.003) * 0.5;
    anchor.y += Math.cos(i + performance.now() * 0.003) * 0.5;
  });
});

Итоговая структура работы

  1. Создание якорей
  2. Назначение типа сегментов
  3. Настройка управляющих точек
  4. Добавление в путь
  5. Динамическое изменение

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