Компонентный подход в контексте Two.js подразумевает разбиение графической сцены на независимые, переиспользуемые элементы — компоненты, каждый из которых управляет своей геометрией, свойствами и поведением. Такой подход повышает масштабируемость кода и облегчает поддержку сложных визуальных проектов.
В Two.js каждый компонент обычно представляется как класс или функция-конструктор, содержащая:
Two.Rectangle,
Two.Circle, Two.Path и т.д.);fill, stroke,
linewidth);Пример создания простого компонента:
class Ball {
constructor(two, x, y, radius, color) {
this.shape = two.makeCircle(x, y, radius);
this.shape.fill = color;
this.shape.noStroke();
}
move(dx, dy) {
this.shape.translation.x += dx;
this.shape.translation.y += dy;
}
setColor(color) {
this.shape.fill = color;
}
}
В этом примере Ball управляет своей позицией и цветом
независимо от других объектов сцены.
Two.js поддерживает группы объектов через
Two.Group, что позволяет объединять несколько компонентов в
один логический блок. Группы упрощают управление положением, масштабом и
видимостью нескольких элементов одновременно.
const group = two.makeGroup();
const ball1 = new Ball(two, 50, 50, 20, '#FF0000');
const ball2 = new Ball(two, 100, 50, 20, '#00FF00');
group.add(ball1.shape, ball2.shape);
group.translation.set(200, 100);
Группа обеспечивает иерархическое управление, где изменение трансформации группы автоматически влияет на все дочерние элементы.
Компоненты должны быть параметризированы для максимальной переиспользуемости. Это включает:
x, y,
radius, width, height);fill, stroke,
opacity);speed, direction,
rotation).Пример универсального компонента прямоугольника:
class RectangleComponent {
constructor(two, options) {
const { x, y, width, height, fill, stroke } = options;
this.shape = two.makeRectangle(x, y, width, height);
this.shape.fill = fill || 'black';
this.shape.stroke = stroke || 'none';
}
resize(width, height) {
this.shape.width = width;
this.shape.height = height;
}
move(dx, dy) {
this.shape.translation.x += dx;
this.shape.translation.y += dy;
}
}
Использование объектов options позволяет создавать
множество вариаций одного и того же компонента без дублирования
кода.
Two.js предоставляет цикл обновления через two.update()
и события two.bind('update', ...). Компоненты могут
самостоятельно управлять своей анимацией, используя внутренние
методы.
two.bind('update', () => {
ball1.move(1, 0); // движение по оси X
ball2.move(-1, 0); // движение в противоположном направлении
});
Компоненты могут содержать внутренние состояния для анимации, такие как скорость, направление или текущее положение, что делает их автономными.
Two.js поддерживает привязку событий к DOM-элементу канваса, что позволяет компонентам реагировать на пользовательские действия. Компоненты могут самостоятельно обрабатывать события, фильтруя их по своей области.
two.renderer.domElement.addEventListener('click', (event) => {
const { offsetX, offsetY } = event;
if (Math.hypot(offsetX - ball1.shape.translation.x, offsetY - ball1.shape.translation.y) < 20) {
ball1.setColor('#0000FF');
}
});
Такая организация позволяет изолировать логику компонентов от общей сцены.
Компонентный подход упрощает создание сложных объектов через наследование. Общие свойства и методы базового компонента выносятся в родительский класс:
class ShapeComponent {
constructor(shape) {
this.shape = shape;
}
move(dx, dy) {
this.shape.translation.x += dx;
this.shape.translation.y += dy;
}
}
class CircleComponent extends ShapeComponent {
constructor(two, x, y, radius, color) {
super(two.makeCircle(x, y, radius));
this.shape.fill = color;
}
}
Наследование позволяет создавать разнообразные элементы с минимальным дублированием кода.
Можно комбинировать несколько простых компонентов для создания более сложных объектов. Например, механическая рука:
class RoboticArm {
constructor(two, baseX, baseY) {
this.base = new RectangleComponent(two, { x: baseX, y: baseY, width: 20, height: 60, fill: '#666' });
this.joint = new CircleComponent(two, baseX, baseY - 30, 10, '#999');
this.hand = new RectangleComponent(two, { x: baseX, y: baseY - 60, width: 10, height: 40, fill: '#333' });
}
rotate(angle) {
this.hand.shape.rotation = angle;
this.joint.shape.rotation = angle;
}
}
Компоненты base, joint и hand
работают как единый объект, но остаются индивидуально
управляемыми.
Этот подход обеспечивает гибкое управление визуальными объектами в Two.js и является основой для разработки интерактивных и анимированных приложений с чистой архитектурой.