В библиотеке Two.js механизм масок (masking) реализован
не на уровне единой абстракции, а зависит от конкретного рендерера. Это
связано с тем, что разные графические технологии — Canvas, SVG и WebGL —
имеют различные нативные возможности и ограничения. В результате
поведение масок может существенно отличаться при переключении рендерера,
что необходимо учитывать при проектировании визуальных сцен.
Общая модель маскирования в
Two.js
Маска в Two.js задаётся через свойство mask у
объекта:
shape.mask = maskShape;
Где:
shape — объект, к которому применяется маска
maskShape — другой объект сцены, определяющий область
видимости
Принцип работы:
- Отображаются только те пиксели
shape, которые попадают
в область maskShape
- Остальная часть скрывается
Однако реализация этого принципа зависит от рендерера.
SVG-рендерер: наиболее
полная поддержка
SVG является самым функционально богатым рендерером в контексте
масок.
Особенности:
- Используется нативный элемент
<mask>
- Поддерживаются сложные формы масок
- Возможна вложенность масок
- Маска может содержать группы (
Group)
- Корректно работает с трансформациями (scale, rotation,
translation)
Преимущества:
- Высокая точность отображения
- Поддержка градиентов и прозрачности внутри маски
- Возможность комбинирования нескольких объектов
Ограничения:
- Производительность снижается при большом количестве сложных
масок
- Поведение зависит от браузера (различия в реализации SVG)
Пример:
var mask = two.makeCircle(100, 100, 50);
var rect = two.makeRectangle(100, 100, 200, 200);
rect.mask = mask;
Canvas-рендерер:
ограниченная поддержка
Canvas не имеет встроенной концепции масок, поэтому Two.js эмулирует
их через операции композиции
(globalCompositeOperation).
Как это реализовано:
- Используется режим
destination-in
- Маска применяется через отрисовку в буфер
Ограничения:
- Только одна маска на объект
- Нет вложенных масок
- Ограниченная поддержка групп
- Потеря производительности при частом обновлении
Проблемы:
- Маска и объект должны находиться в одном контексте отрисовки
- Невозможность повторного использования маски без повторного
рендера
- Сложности при анимации маски
Особенности поведения:
- Маска фактически «обрезает» уже нарисованный объект
- Порядок отрисовки критически важен
WebGL-рендерер:
частичная и нестабильная поддержка
WebGL в Two.js реализует маски через шейдеры и буферы, однако
поддержка ограничена и может отличаться в зависимости от реализации
версии библиотеки.
Технический подход:
- Использование stencil buffer или alpha masking
- Дополнительные проходы рендера
Ограничения:
- Поддержка масок может быть отключена или частично реализована
- Нет гарантии корректной работы для сложных сцен
- Ограниченная совместимость с группами
Проблемы:
- Высокая сложность реализации
- Зависимость от GPU и драйверов
- Возможны артефакты (мерцание, некорректные границы)
Практические ограничения:
- Простые геометрические маски работают стабильно
- Сложные векторные формы могут не поддерживаться
- Анимация масок требует дополнительной оптимизации
Сравнение возможностей
| Возможность |
SVG |
Canvas |
WebGL |
| Простые маски |
Да |
Да |
Частично |
| Сложные формы |
Да |
Ограничено |
Ограничено |
| Вложенные маски |
Да |
Нет |
Нет |
| Маски для групп |
Да |
Частично |
Ограничено |
| Анимация масок |
Да |
Медленно |
Сложно |
| Производительность |
Средняя |
Высокая |
Высокая |
| Кроссбраузерность |
Средняя |
Высокая |
Зависит от GPU |
Ограничения при работе с
группами
Группы (Two.Group) ведут себя по-разному в зависимости
от рендерера:
- SVG: маска применяется ко всей группе
корректно
- Canvas: маска применяется к результату отрисовки
группы, что может давать неожиданные эффекты
- WebGL: поддержка нестабильна, особенно при
вложенных группах
Ключевая проблема:
- В Canvas и WebGL группа сначала рендерится, затем применяется маска
как к единому изображению
Влияние трансформаций
Трансформации маски и объекта:
- SVG: трансформации независимы и корректно
комбинируются
- Canvas: трансформации могут «запекаться» в итоговом
изображении
- WebGL: возможны рассинхронизации координат
Практическое следствие:
- При анимации положения маски в Canvas часто требуется перерасчёт
всей сцены
Ограничения прозрачности
и градиентов
- SVG: полная поддержка альфа-канала и
градиентов
- Canvas: альфа работает, но градиенты внутри маски
могут вести себя непредсказуемо
- WebGL: зависит от реализации шейдеров
Порядок отрисовки и его
влияние
Особенно критично для Canvas:
- Маска должна быть применена после отрисовки объекта
- Нарушение порядка приводит к отсутствию эффекта маски
В SVG порядок менее критичен, так как используется декларативная
модель.
Производительность и
оптимизация
SVG:
- Увеличение количества масок → рост DOM → падение
производительности
Canvas:
- Частые операции композиции → нагрузка на CPU
- Лучше минимизировать количество масок
WebGL:
- Дополнительные проходы рендера → нагрузка на GPU
- Требуется batching и оптимизация сцен
Практические рекомендации
Выбор рендерера:
- SVG — для сложных масок, высокой точности и визуальных эффектов
- Canvas — для простых масок и высокой производительности
- WebGL — для экспериментов и сложной графики с осторожностью
Оптимизация:
- Избегать вложенных масок вне SVG
- Уменьшать количество динамических масок
- Использовать простые формы вместо сложных путей
Архитектурные решения:
- Разделять сцены по рендерерам при необходимости
- Предварительно тестировать поведение масок
- Закладывать ограничения рендерера в дизайн
Частые проблемы и причины
Маска не отображается:
- Объект и маска в разных группах (Canvas)
- Неправильный порядок добавления в сцену
Артефакты:
- WebGL: проблемы с буфером трафарета
- Canvas: наложение нескольких масок
Падение производительности:
- Частая анимация масок
- Сложные SVG-пути
Поведение при переключении
рендерера
При смене рендерера (например, с SVG на Canvas):
- Маски могут исчезнуть или упроститься
- Вложенные структуры перестают работать
- Визуальный результат меняется
Это делает важным тестирование сцены в целевом рендерере с самого
начала разработки.
Ограничения
повторного использования масок
- SVG: маска может использоваться повторно
несколькими объектами
- Canvas: требуется повторная отрисовка
- WebGL: зависит от реализации, часто ограничено
Влияние на архитектуру
приложения
Из-за различий в поддержке масок:
- Логика сцены должна учитывать рендерер
- Нельзя полностью абстрагироваться от графического бэкенда
- Маски становятся частью архитектурных ограничений, а не только
визуального слоя
Это особенно важно в сложных интерактивных приложениях и редакторах
графики, где маскирование используется активно.