Разделение логики рендеринга

Для работы с Two.js первым шагом является создание экземпляра движка и привязка его к HTML-контейнеру. Основной объект Two создается с помощью конструктора, который принимает объект конфигурации:

const elem = document.getElementById('draw-area');
const two = new Two({
  width: 800,
  height: 600,
  type: Two.Types.svg // или Two.Types.canvas, Two.Types.webgl
}).appendTo(elem);

Ключевые параметры:

  • width и height – размеры области рендеринга.
  • type – тип рендеринга: svg, canvas или webgl.
  • Метод appendTo привязывает canvas/SVG к конкретному элементу DOM.

После этого объект Two.js готов к созданию графических объектов и анимации.


Разделение логики рендеринга и управления данными

Основная идея Two.js заключается в том, что логика создания графики и рендеринг могут быть разделены. Для этого рекомендуется использовать следующие слои:

  1. Слой данных (Model Layer) – хранит информацию о фигурах, их свойствах и взаимосвязях.
  2. Слой рендеринга (View Layer) – отвечает за визуальное представление объектов на канве.
  3. Слой управления (Controller Layer) – управляет анимацией, обработкой событий и синхронизацией данных с визуальными элементами.

Пример структуры:

const model = {
  circles: [
    { x: 100, y: 100, radius: 50, color: '#FF0000' },
    { x: 300, y: 150, radius: 75, color: '#00FF00' }
  ]
};

const view = model.circles.map(data => {
  return two.makeCircle(data.x, data.y, data.radius).fill = data.color;
});

two.update();

Здесь данные полностью отделены от визуального представления, что позволяет легко обновлять сцену без пересоздания всей графики.


Использование групп и сцен

Two.js поддерживает группы (Two.Group), которые позволяют объединять объекты и управлять ими как единым целым. Это особенно полезно для сложных сцен.

const group = two.makeGroup();
const circle1 = two.makeCircle(50, 50, 30);
const circle2 = two.makeCircle(150, 50, 30);

group.add(circle1, circle2);
group.translation.set(200, 100); // смещение всей группы

Преимущества групп:

  • Позволяют перемещать, масштабировать и вращать несколько объектов одновременно.
  • Упрощают организацию сцены.
  • Сохраняют связь объектов с данными, если использовать соответствующие структуры.

Анимация и разделение логики обновления

Two.js использует метод bind для создания анимаций через рендеринг кадр за кадром. Разделение логики анимации и рендеринга помогает поддерживать чистый код.

two.bind('update', function(frameCount, timeDelta) {
  model.circles.forEach((data, i) => {
    data.x += 0.5;
    view[i].translation.x = data.x;
  });
}).play();

Особенности подхода:

  • Model Layer содержит текущие координаты и состояния объектов.
  • View Layer обновляет графику на основе данных модели.
  • Анимационный цикл Two.js вызывает update на каждом кадре, что гарантирует плавное движение.

Использование отдельных функций для рендеринга

Разделение функций рендеринга позволяет держать код чистым и модульным. Например, можно создать функцию renderCircle, которая отвечает только за визуализацию данных:

function renderCircle(data) {
  const circle = two.makeCircle(data.x, data.y, data.radius);
  circle.fill = data.color;
  return circle;
}

const view = model.circles.map(renderCircle);

Такой подход упрощает:

  • Обновление отдельных объектов без изменения всей сцены.
  • Поддержку разных форм визуализации для одних и тех же данных.
  • Интеграцию с другими библиотеками или пользовательским интерфейсом.

События и пользовательское взаимодействие

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

view.forEach((circle, i) => {
  circle._renderer.elem.addEventListener('click', () => {
    model.circles[i].color = '#0000FF';
    circle.fill = model.circles[i].color;
    two.update();
  });
});

Здесь события изменяют только модель, а визуальное представление синхронизируется отдельно. Это повышает гибкость и масштабируемость проектов.


Практика масштабируемой архитектуры

Для больших проектов рекомендуется:

  1. Создавать отдельные модули для модели, вида и контроллера.
  2. Использовать Two.Group для структурирования сцен.
  3. Делать анимации через two.bind('update', ...) и обновлять только необходимые объекты.
  4. Хранить состояния объектов в массиве или классе модели, чтобы легко применять эффекты, фильтры или взаимодействие.

Пример организации:

/model
  circles.js
/view
  circlesView.js
/controller
  animationController.js

Такой подход обеспечивает масштабируемость и поддерживаемость, особенно при работе с интерактивной анимацией и сложными сценами.