Применение масок к объектам и группам

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

В основе механизма лежит свойство mask, доступное у всех объектов сцены, включая группы (Two.Group) и примитивы (Two.Path, Two.Rectangle, Two.Circle и др.).


Принцип работы маски

Маска — это отдельный объект Two.js, который применяется к другому объекту или группе:

  • Белые (или непрозрачные) области маски — показывают содержимое
  • Прозрачные области — скрывают содержимое

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


Применение маски к объекту

var two = new Two({ width: 500, height: 500 }).appendTo(document.body);

// Основной объект
var rect = two.makeRectangle(250, 250, 300, 300);
rect.fill = 'blue';

// Маска
var circle = two.makeCircle(250, 250, 150);

// Применение маски
rect.mask = circle;

two.update();

Результат: Прямоугольник будет виден только внутри круга.


Маскирование группы объектов

Маски можно применять не только к одиночным фигурам, но и к группам. Это позволяет управлять видимостью сразу нескольких элементов.

var group = two.makeGroup();

var rect1 = two.makeRectangle(200, 250, 150, 150);
rect1.fill = 'red';

var rect2 = two.makeRectangle(300, 250, 150, 150);
rect2.fill = 'green';

group.add(rect1, rect2);

// Маска
var maskShape = two.makeCircle(250, 250, 120);

// Применение маски к группе
group.mask = maskShape;

two.update();

Особенность: Маска применяется ко всей группе как к единому целому, а не к каждому объекту отдельно.


Иерархия и вложенные маски

Two.js поддерживает вложенные структуры:

  • Группа может содержать другие группы
  • Маска может применяться на любом уровне
var parentGroup = two.makeGroup();
var childGroup = two.makeGroup();

var rect = two.makeRectangle(250, 250, 200, 200);
rect.fill = 'orange';

childGroup.add(rect);
parentGroup.add(childGroup);

// Маска для родительской группы
var mask = two.makeCircle(250, 250, 100);
parentGroup.mask = mask;

Поведение: Маска верхнего уровня влияет на всё содержимое, включая вложенные группы.


Трансформации маски

Маска — полноценный объект сцены, поэтому к ней применяются все трансформации:

  • translation
  • rotation
  • scale
mask.translation.set(300, 250);
mask.scale = 1.5;
mask.rotation = Math.PI / 4;

Важно: Трансформации маски напрямую влияют на область видимости, создавая динамические эффекты.


Анимация масок

Маски часто используются для анимации появления и исчезновения объектов.

Пример: эффект “проявления”

two.bind('upd ate', function(frameCount) {
  mask.scale += 0.01;
});

Эффект: Объект постепенно становится видимым по мере увеличения маски.


Пример: перемещающаяся маска

two.bind('update', function(frameCount) {
  mask.translation.x = 250 + Math.sin(frameCount * 0.05) * 100;
});

Эффект: Создаётся “окно”, через которое виден объект.


Маска как сложная форма

Маска может быть не только простой фигурой, но и сложным контуром:

var path = two.makePath(
  200, 200,
  300, 200,
  350, 300,
  250, 350,
  150, 300,
  true
);

rect.mask = path;

Особенность: Используются произвольные многоугольники и кривые.


Использование нескольких уровней масок

Хотя у одного объекта может быть только одна маска, можно создавать сложные эффекты через вложенность:

var group1 = two.makeGroup();
var group2 = two.makeGroup();

group1.add(group2);

group1.mask = mask1;
group2.mask = mask2;

Результат: Комбинированное маскирование через иерархию.


Ограничения и особенности

1. Одна маска на объект

Каждому объекту или группе можно назначить только одну маску:

object.mask = mask;

2. Маска должна быть в сцене

Если маска не добавлена в сцену или группу, она не будет работать корректно.

3. Порядок рендеринга

Маска не зависит от визуального порядка (z-index), а определяется логически через свойство mask.

4. Производительность

Сложные маски (особенно анимированные) могут снижать производительность, особенно при:

  • большом количестве вершин
  • частых обновлениях
  • вложенных группах

Практические сценарии применения

Окно просмотра (viewport)

Ограничение видимой области:

group.mask = two.makeRectangle(250, 250, 200, 200);

Эффект “прожектора”

Круглая маска, перемещающаяся по сцене:

mask.translation.se t(mouseX, mouseY);

Анимация загрузки

Использование дуги или круга как маски:

mask.scale = progress; // от 0 до 1

Вырезание формы

Создание сложных композиций через наложение:

  • текст внутри фигуры
  • изображение внутри контура
  • динамические переходы

Сравнение с clip-path и canvas clipping

Подход Особенности
Two.js mask Простота, объектная модель
Canvas clip() Низкоуровневый контроль
CSS clip-path Ограничен DOM и браузером

Two.js предоставляет баланс между удобством и гибкостью.


Взаимодействие с SVG-рендерером

При использовании SVG-рендеринга маски преобразуются в <mask> или <clipPath>:

  • сохраняется векторная точность
  • возможна интеграция с DOM
  • упрощается отладка через инспектор браузера

Рекомендации по использованию

  • Использовать простые формы для масок при анимации
  • Избегать глубоких вложенностей без необходимости
  • Контролировать количество вершин в сложных путях
  • При сложных эффектах комбинировать маски с прозрачностью (opacity)

Внутреннее устройство свойства mask

Свойство mask — это ссылка на объект сцены:

object.mask = anotherObject;

При рендеринге движок:

  1. Рисует маску в отдельный буфер
  2. Применяет её к целевому объекту
  3. Отображает результат

Это абстрагировано от разработчика, но важно понимать для оптимизации.


Комбинирование с другими свойствами

Маски эффективно работают вместе с:

  • opacity — плавные переходы
  • scale — анимации раскрытия
  • rotation — динамические эффекты
  • translation — движение области видимости

Типичные ошибки

Маска не работает:

  • не добавлена в сцену
  • имеет нулевой размер
  • неправильно позиционирована

Объект полностью скрыт:

  • маска находится вне области объекта
  • масштаб слишком мал

Низкая производительность:

  • слишком сложный путь
  • частые изменения геометрии

Архитектурный подход

При проектировании сцены:

  • маски лучше выносить в отдельные группы
  • использовать повторно, если возможно
  • разделять статические и анимируемые элементы

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