Процедурная генерация форм

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

const elem = document.getElementById('drawing');
const two = new Two({
  width: 800,
  height: 600,
  type: Two.Types.webgl
}).appendTo(elem);

Ключевые моменты:

  • width и height задают размеры области рисования.
  • type определяет рендерер, что важно для производительности и совместимости.
  • Метод appendTo привязывает канвас к DOM-элементу.

Простейшие формы и их свойства

Two.js предоставляет встроенные классы для базовых фигур: Rectangle, Circle, Polygon, Ellipse, Path. Каждая фигура имеет свойства позиция, размер, цвет заливки, цвет обводки, толщину линии.

const circle = two.makeCircle(200, 200, 50);
circle.fill = '#FF8000';
circle.stroke = '#000000';
circle.linewidth = 3;
  • makeCircle(x, y, radius) создаёт круг с центром (x, y).
  • fill задаёт цвет заливки, stroke — цвет контура.
  • linewidth управляет толщиной контура.

Процедурная генерация форм

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

for (let i = 0; i < 10; i++) {
  const x = Math.random() * 800;
  const y = Math.random() * 600;
  const radius = Math.random() * 50 + 10;
  const color = `rgb(${Math.floor(Math.random()*255)}, ${Math.floor(Math.random()*255)}, ${Math.floor(Math.random()*255)})`;

  const circle = two.makeCircle(x, y, radius);
  circle.fill = color;
  circle.noStroke();
}

Принципы процедурной генерации:

  • Случайные значения создают вариативность форм.
  • Математические функции позволяют формировать закономерные паттерны (например, спирали или волны).
  • Цветовые градиенты и альфа-прозрачность усиливают визуальную глубину.

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

Генерацию объектов можно структурировать через функции:

function generateGrid(rows, cols, spacing) {
  for (let i = 0; i < rows; i++) {
    for (let j = 0; j < cols; j++) {
      const size = Math.random() * 30 + 10;
      const rect = two.makeRectangle(j * spacing, i * spacing, size, size);
      rect.fill = `hsl(${Math.random() * 360}, 70%, 50%)`;
      rect.noStroke();
    }
  }
}

generateGrid(10, 15, 60);
  • rows и cols задают количество элементов.
  • spacing определяет расстояние между фигурами.
  • Использование hsl позволяет динамически менять оттенок при генерации.

Применение анимаций при процедурной генерации

Two.js интегрирует анимации через функцию two.update и объекты Tween для плавного изменения свойств:

two.bind('update', function(frameCount) {
  for (let shape of two.scene.children) {
    shape.rotation += 0.01;
    shape.scale = 0.5 + 0.5 * Math.sin(frameCount * 0.05);
  }
}).play();
  • two.bind('update', callback) вызывается на каждом кадре анимации.
  • Изменение rotation и scale создаёт динамическую визуализацию.
  • Процедурные формы можно комбинировать с тригонометрическими функциями для органичных движений.

Сложные формы и Path генерация

Path позволяет создавать произвольные фигуры с использованием точек и кривых Безье:

const path = two.makePath(0, 0, 100, 50, 50, 150, true);
path.fill = 'rgba(0, 128, 255, 0.5)';
path.stroke = '#0055FF';
path.linewidth = 2;
  • Последний параметр true закрывает путь, создавая замкнутую фигуру.
  • Метод vertices позволяет манипулировать каждой точкой динамически.
  • Использование процедурных алгоритмов для изменения вершин создаёт уникальные формы на каждом кадре.

Комбинирование процедурных элементов

Можно создавать сцены, где разные алгоритмы взаимодействуют:

function generateScene() {
  generateGrid(8, 12, 70);
  
  for (let i = 0; i < 20; i++) {
    const x = Math.random() * 800;
    const y = Math.random() * 600;
    const radius = Math.random() * 40 + 10;
    const circle = two.makeCircle(x, y, radius);
    circle.fill = `rgba(255, 0, 0, ${Math.random()})`;
    circle.noStroke();
  }
}

generateScene();
two.update();
  • Комбинирование сетки и случайных объектов создаёт сложные, но структурированные визуальные композиции.
  • Альфа-прозрачность позволяет формировать эффект наложения и глубины.

Настройка интерактивности

Процедурные формы можно делать интерактивными, реагируя на события мыши:

two.renderer.domElement.addEventListener('mousemove', function(event) {
  const x = event.offsetX;
  const y = event.offsetY;
  const radius = Math.random() * 20 + 5;
  const circle = two.makeCircle(x, y, radius);
  circle.fill = 'rgba(0, 255, 128, 0.7)';
  circle.noStroke();
  two.update();
});
  • Каждое движение мыши создаёт новую фигуру.
  • Интерактивные элементы добавляют динамику и непредсказуемость в процедурно сгенерированную сцену.
  • Подобные подходы позволяют создавать игры, визуализации данных и интерактивные арт-объекты.

Оптимизация процедурной генерации

  • Использовать группы объектов (two.makeGroup) для управления множеством фигур одновременно.
  • Ограничивать количество одновременно отображаемых объектов для производительности.
  • Применять динамическое обновление вершин вместо создания новых объектов каждый кадр, когда это возможно.
const group = two.makeGroup();
for (let i = 0; i < 50; i++) {
  const rect = two.makeRectangle(Math.random()*800, Math.random()*600, 20, 20);
  rect.fill = '#FFCC00';
  rect.noStroke();
  group.add(rect);
}
group.rotation = Math.PI / 4;
two.update();
  • Группы позволяют поворачивать, масштабировать или перемещать сразу все элементы.
  • Значительно упрощают управление сложными сценами с сотнями процедурных объектов.