SVG-маски

Содержание:
maskUnits
maskContentUnits
X и Y
Width и height
Примеры использования

SVG-маски — это очень богатая тема. В SVG есть два способа обрезать один элемент с помощью другого: это clip-path и mask. Clip-path для обрезки использует только контуры фигур, игнорируя заливки и обводки, с масками всё гораздо интереснее: в них учитываются и заливки, и обводки, и яркость содержимого. Более того, в маску можно вставить растровое изображение, и тогда для создания маски будут использоваться его темные и светлые участки.

Код самой простой маски выглядит вот так:

<mask id="mask">
  <!-- содержимое маски -->
</mask>

Добавим пару фигур для примера:

<mask id="mask">
  <g stroke="gray" stroke-width="12" fill="white">
    <circle cx="33%" cy="30%" r="20%" />
    <circle cx="52%" cy="62%" r="32%" />
  </g>
</mask>

Картинка + маска = результат:

Код маски задаётся внутри SVG и может быть использован как внутри этого элемента, так и в других SVG-элементах на той же странице. Также есть возможность использовать SVG-маски в CSS (например, mask: url(#mymask)), но на данный момент это работает только в Firefox.

Единственным обязательными атрибутом элемента mask является id — это идентификатор, который нужен для подключения маски к элементу, но есть и другие атрибуты:

maskUnits

Определяет, какая система координат будет использоваться для атрибутов x, y, width и height, то есть для внешних размеров и координат.

Возможные значения:

userSpaceOnUse — используется текущая система координат элемента, к которому применяется маска. Если не применялись трансформации, соответствует системе координат всего документа (например, width: 100% будет равно ширине всего SVG-элемента).

objectBoundingBox — атрибуты x, y,

width и height задаются в частях или процентах от размеров элемента, к которому применяется маска (width: 100% будет равно ширине элемента с маской).

Если maskUnits не задано, используется значение objectBoundingBox.

Попереключайте значения maskUnits и посмотрите как меняется поведение маски:

С objectBoundingBox 50% рассчитываются относительно элемента, с userSpaceOnUse — относительно всего документа.

С objectBoundingBox координаты и размеры можно задавать и в частях от целого, и в процентах, то есть .5 здесь то же самое, что и 50%. При userSpaceOnUse будут работать только процентные значения либо значения в абсолютных единицах, например, в пикселях.

maskContentUnits

Определяет, какая система координат будет использоваться для содержимого маски, то есть для внутренних размеров и координат.

Возможные значения:

userSpaceOnUse — для содержимого маски используется текущая система координат элемента, к которому применяется маска (без трансформаций соответствует системе координат всего SVG-элемента).

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

Если атрибут maskContentUnits не задан, используется значение userSpaceOnUse.

Обратите внимание, что при objectBoundingBox фигуры могут искажаться (в данном случае круг превращается в эллипс).

В отличие от maskUnits, при objectBoundingBox координаты и размеры можно задавать только в частях от целого (возможные значения — от 0 до 1), значения в процентах работать не будут.

То есть не то чтобы совсем не будут — процентные значения будут рассчитываться относительно размеров всего SVG, и в этом случае .5 совсем не равно 50%, потому что .5 — это половина элемента с маской, а 50% — это уже половина всего SVG-изображения. И если вы будете менять значения maskContentUnits, вам придётся каждый раз переписывать размеры и координаты содержимого маски.

Мне не сразу удалось понять как это работает, спасибо SelenIT2 и AmeliasBrain за то, что помогли разобраться в вопросе.

X и Y

Определяют, где будет находиться верхний левый угол отображаемой области маски. Содержимое маски при этом не сдвигается.

Для x и y значение по умолчанию 10%.

Width и height

Определяют, где будет находиться нижний правый угол отображаемой области маски. Внешние размеры маски не влияют на размеры её содержимого.

Для width и height значение по умолчанию 120%.

Вместе параметры x,y, width и height работают как viewBox, то есть определяют размеры отображаемой области маски:

Знание всех этих технических подробностей позволит не сойти с ума при работе с масками и их своеобразными системами координат.

Примеры использования

Маски можно (и нужно) использовать для создания визуальных эффектов. Правда, мне пока не приходилось использовать маски в реальных проектах, но экспериментировать с ними очень увлекательно. Внимание: лучше всего демо отображаются в Opera и Chrome. В Firefox могут не работать некоторые анимации, в Safari воообще беда.

Например, с помощью маски можно вырезать фигуру нужной формы, анимировать её содержимое и собрать калейдоскоп.

Или привязать фигуру внутри маски к координатам курсора и получить фонарик (наведите курсор на демо):

Ещё интереснее заворачивать в маску растровые изображения (в отличие от векторных, они могут быть любой сложности, с множеством деталей и мелких штрихов):

Автор совы: BioWorkZ

Подобное можно сделать с любой чёрно-белой картинкой, и для этого даже не придется открывать графический редактор.

Изображение в маске может быть анимированным (и заливка для него тоже!):

(Если птица показалась вам знакомой, вам не показалось.)

Также с помощью маски можно сделать анимированную заливку для текста:

А ещё можно динамически менять векторное содержимое маски и сделать исчезающие надписи или, например, часы:

Или эффектную фотогалерею (туториал):

Маски удивительные, играться с ними можно до бесконечности. И, по-моему, они несут в себе огромный потенциал, который мы только-только начинаем открывать.

Ссылки по теме:
Clip path
Masking
CSS и SVG маски (статья)
Все виды масок в CSS и SVG (демо)
Анимированные SVG-маски
SVG: полезные ссылки
Множество демо с масками на Codepen
Умная прокрутка со Scroll Snap PointsВесёлая консолька
Наверх