Создание масок отсечения

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

В основе механизма лежит идея: один объект используется как «трафарет» (маска), через который виден другой объект. Всё, что выходит за пределы маски, не отображается.


Базовая концепция

В Two.js любой графический объект является экземпляром класса Two.Shape или его производных (Two.Path, Two.Rectangle, Two.Circle и др.). Маска также представляет собой обычную фигуру, но используется особым образом.

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

shape.mask = maskShape;
  • shape — объект, к которому применяется маска
  • maskShape — объект, определяющий видимую область

После назначения маски:

  • видимой остаётся только та часть shape, которая пересекается с геометрией маски
  • сама маска может быть невидимой (обычно так и делается)

Простой пример маскирования

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

// Основной объект (например, изображение или фигура)
const rect = two.makeRectangle(250, 250, 300, 300);
rect.fill = 'blue';

// Маска — круг
const mask = two.makeCircle(250, 250, 100);
mask.fill = 'black';

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

// Скрываем маску
mask.visible = false;

two.update();

Результат: синий квадрат будет виден только внутри круглой области.


Особенности координат и трансформаций

Маска и объект существуют в одной системе координат. Это означает:

  • любые трансформации (translation, rotation, scale) применяются независимо
  • важно учитывать относительное положение объектов

Пример смещения маски:

mask.translation.set(300, 250);

Это изменит область видимости объекта без изменения самого объекта.


Маски и группы

Two.js активно использует группы (Two.Group) для организации сцены. Маска может применяться не только к отдельной фигуре, но и к группе:

const group = two.makeGroup(rect1, rect2, rect3);
group.mask = mask;

В этом случае:

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

Вложенные маски

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

shape.mask = mask1;
mask1.mask = mask2;

Однако на практике:

  • сложные цепочки масок могут ухудшать производительность
  • визуальный результат зависит от рендерера (Canvas, SVG, WebGL)

Маскирование изображений

Маски особенно полезны при работе с изображениями:

const image = two.makeImage('image.jpg', 250, 250);
const mask = two.makeCircle(250, 250, 120);

image.mask = mask;
mask.visible = false;

Применение:

  • аватары (круглые, овальные)
  • обрезка изображений
  • эффекты появления

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

Маска — это обычный объект, значит её можно анимировать:

two.bind('upd ate', function(frameCount) {
  mask.scale = 1 + Math.sin(frameCount * 0.05) * 0.5;
});

Эффекты:

  • «пульсирующее» окно
  • раскрытие/закрытие сцены
  • динамическое освещение

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

Маска не ограничивается простыми фигурами. Можно использовать произвольные пути:

const path = two.makePath(
  200, 200,
  300, 100,
  400, 200,
  350, 300,
  250, 300,
  true
);

shape.mask = path;
path.visible = false;

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

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

Работа с прозрачностью

Важно понимать:

  • маска учитывает геометрию, а не цвет
  • прозрачность (opacity) маски не влияет на силу маскирования

Исключение: при использовании SVG-рендера возможны нюансы, связанные с альфа-каналом.


Маски и порядок рендеринга

Two.js использует иерархию сцены:

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

Рекомендуемый подход:

two.add(mask);
two.add(shape);
shape.mask = mask;

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

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

  • Canvas
  • SVG
  • WebGL

Поведение масок может отличаться:

Canvas:

  • быстрее
  • иногда менее точное маскирование

SVG:

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

WebGL:

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

Оптимизация производительности

Маскирование — ресурсоёмкая операция. Рекомендации:

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

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

1. Прогресс-бары

  • маска изменяет ширину или форму
  • создаёт эффект заполнения

2. Эффекты появления

  • маска «раскрывает» объект
  • используется в анимациях интерфейса

3. Параллакс

  • разные слои маскируются по-разному
  • создаётся глубина сцены

4. Имитация освещения

  • маска в форме круга или градиента
  • создаёт эффект «фонарика»

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

Маски можно сочетать с:

  • opacity
  • scale
  • rotation
  • translation

Пример:

mask.rotation += 0.01;
mask.scale = 1 + Math.sin(frameCount * 0.1) * 0.2;

Это даёт сложные динамические эффекты без изменения самого объекта.


Отладка масок

При проблемах с отображением:

  • временно включать видимость маски:

    mask.visible = true;
  • проверять координаты

  • упрощать форму маски

  • тестировать в разных рендерерах


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

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

  • отдельные функции для создания масок
  • переиспользуемые компоненты

Композиция:

  • маска как часть объекта
  • использование групп для управления

Анимационные контроллеры:

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

Частые ошибки

  • Маска не добавлена в сцену
  • Неправильные координаты
  • Маска перекрывает объект визуально (не отключена visible)
  • Слишком сложная геометрия
  • Несовместимость с выбранным рендерером

Расширенные техники

Динамическая смена маски:

shape.mask = mask1;

// позже
shape.mask = mask2;

Интерактивные маски:

document.addEventListener('mousemove', (e) => {
  mask.translation.se t(e.clientX, e.clientY);
});

Маски с анимацией пути:

  • изменение вершин (vertices)
  • создание «живых» форм

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