От автора: две часто применяемые операции в компьютерной графике – это обрезка (clip) и наложение маски (mask). Обе операции скрывают видимые части элемента. Если вы до этого работали с SVG или HTML Canvas, то они, скорее всего, не новы для вас. Обрезка определяет видимую область элемента. Все, находящееся вокруг этой области, не видно – оно «отсекается». При наложении маски изображение-маска компонуется с элементом, влияя на альфа-канал этого элемента. Детали элемента с наложенной маской становятся полностью или частично прозрачными. Новая спецификация CSS Masking ставит своей целью укоренить эти две операции в мире HTML.
Обрезка в CSS 2.1
CSS 2.1 уже занесли в спецификации свойство clip. Оно ограничено до прямоугольной обрезки с помощью функции rect(), принимающей четыре аргумента расстояния для верхнего, правого, нижнего и левого краев. Раздражает следующее: свойство clip применяется исключительно к абсолютно позиционированным элементам. В других элементах оно просто игнорируется.
1 2 3 4 |
img { position: absolute; clip: rect(10px, 290px, 190px, 10px); } |
1 |
<img src="image.jpg" width="568"> |
Свойство clip также ограничено до определенных элементов в SVG. Это причина того, почему спецификация SVG добавила свойство clip-path, которое сейчас адаптировано к CSS Masking.
Свойство clip-path
Свойство clip-path можно применять ко всем элементам HTML, графическим элементам SVG и элементам-контейнерам SVG. Оно также ссылается на элемент clipPath или одну из базовых фигур, представленных CSS Exclusions.
Элемент
1 2 3 |
img { clip-path: url(#clipping); } |
1 2 3 4 5 6 7 8 9 |
<svg> <defs> <clipPath id="clipping"> <circle cx="284" cy="213" r="213" /> </clipPath> </defs> </svg> <img src="image.jpg" width="568"> |
С другой стороны, базовые фигуры не требуют разметки SVG. Они добавлены в clip-path для быстроты написания простых операций отсечения.
rectangle(top, left, width, height, rx, ry) определяет прямоугольник, аналогично функции rect() для clip, и добавляет два опциональных параметра радиуса для скругленных прямоугольников.
circle(cx, cy, r) определяет простую окружность с центром и радиусом.
ellipse(cx, cy, rx, ry) определяет овал с центром и горизонтальным и вертикальным радиусами.
polygon(x1 y1, x2 y2, …, xn yn) определяет многоугольник на основе переданного списка точек.
Разметка CSS может выглядеть, как в следующем примере:
1 2 3 |
img { clip-path: polygon(0px 208px, 146.5px 207px, 147px 141.2px, ...); } |
Обрезка может оказаться очень нужным при представлении визуального контента. Следующие примеры применяют к изображениям различные операции отсечения.
Но обрезка также очень нужно для дизайна UI. В следующем примере V-шеврон обозначает продолжающийся список.
Заметьте, что clip-path (а также clip) отсекают любой аспект элемента, включая фоны, края и любые механизмы прокрутки.
Анимация clip-path
Как базовые фигуры, так и содержимое элемента mask можно анимировать. В следующем примере – анимация в форме звезды:
Вот исходный код анимации базовой фигуры:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
img:hover { clip-path: polygon(0px 208px, 146.5px 207px, 147px 141.2px, ...); animate: star 3s; } @keyframes star { 0% { clip-path: polygon(0px 208px, 146.5px 207px, 147px 141.2px, ...); }, 100% { clip-path: polygon(0px 208px, 146.5px 207px, 147px 141.2px, ...); } } |
Наложение маски
Вторая операция после обрезки – это наложение маски. Изображение-маска применяется как некий вид «цветовой сетки» для фильтрации видимых частей элемента. В следующих абзацах я объясню разницу между двумя типами маски: цветовой насыщенности и альфа-маской.
Маска цветовой насыщенности
Для маски цветовой насыщенности изображение-маска сначала превращается в растеризованное изображение шкалы яркости (если оно уже не в шкале яркости). Чем «светлее» часть изображения-маски, тем больше в данном месте будет видно элемента под наложенной маской. Например, черный означает полную прозрачность, белый означает полную непроницаемость и серый тон означает частичную прозрачность элемента.
Альфа-маска
Наложение альфа-маски использует те же принципы, что и маски цветовой насыщенности. Отличие от последней: имеет значение только альфа-канал изображения. Чем менее непроницаема часть изображения-маски, тем менее видным будет элемент в том же месте.
Резюме: оба вида наложения масок влияют на уровень прозрачности элемента. Изображение внизу – результат обеих операций наложения масок.
Спецификация CSS Masking определяет две сокращенных записи свойства наложения масок: mask и mask-box-image.
Свойство mask
Свойство mask сочетает наложение маски на изображение со ссылкой на маску как описано ниже.
Первый способ – применение свойств mask-image, mask-repeat, mask-position, mask-clip, mask-origin и mask-size, которые устанавливаются аналогично их эквиваленту background с background-image. Как для background-image, можно определить множество источников маски. Каждая маска-источник – это изображение, определенное изображениями CSS3 (CSS3 Images). Все источники комбинируются для формирования одного изображения. Оно используется для наложения маски на элемент и его содержимое, как описано выше. Возможные значения изображений — это любые растровые форматы изображений, вроде JPG или PNG, графика SVG или предустановленные значения изображений, как градиенты CSS.
Первый вышеприведенный пример наложения маски можно просто реализовать при помощи следующего кода:
1 2 3 |
img { mask-image: url(mask.svg); } |
Если маску-источник нужно растянуть до размера содержимого, просто примените сокращенное свойство mask, как вы сделали бы это для фона с помощью сокращенной записи свойства background:
1 2 3 |
img { mask: url(mask.svg) top left / cover; } |
Второй способ обращается к элементу mask, как это определено в SVG 1.1. Элемент mask принимает любой графический элемент, а также сгруппированные элементы из SVG, и применяет их для создания изображения-маски.
1 2 3 |
img { mask: url(#masking); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<svg> <defs> <linearGradient id="gradient" x1="0" y1="00%" x2 ="0" y2="100%"> <stop stop-color="black" offset="0"/> <stop stop-color="white" offset="1"/> </linearGradient> <mask id="masking" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox"> <rect y="0.3" width="1" height=".7" fill="url(#gradient)" /> <circle cx=".5" cy=".5" r=".35" fill="white" /> </mask> </defs> </svg> <img src="image.jpg" width="568"> |
Что будет смотреться, как следующее изображение:
Свойство mask-box-image
Свойство mask-box-image позволяет разделить изображение-маску на девять мозаичных элементов: четыре угла, четыре края и середину. Эти части можно раскладывать на слои, масштабировать и растягивать разными способами, чтобы те подошли к размеру области изображения-маски. Это свойство заимствует свою функциональность у border-image и дает возможность наложения мощной маски с краев и углов содержимого. Этот пример показывает характер поведения данного свойства:
1 2 3 |
img { mask-box-image: url("stamp.svg") 35 repeat; } |
Следующее изображение используется как маска и поделено на девять частей:
Эти части теперь используются для наложения маски на углы и края содержимого, а результат можно видеть тут:
Браузерная поддержка
Браузерная поддержка – интересная тема. Когда дело доходит до определения свойства, становится трудновато.
Все браузеры, как заявлено, поддерживают clip. Все браузеры поддерживают свойства mask и clip-path, как определено в SVG 1.1 для элементов SVG. Но только один браузер дает вам возможность применять эти свойства к элементам HTML: Firefox (как бы). Давайте разберемся подробнее.
Свойства clip-path и mask со ссылкой на элементы clipPath и mask замечательно работают в Firefox’е; оба свойства без префиксов. С другой стороны, свойства mask-image, mask-box-image и связанные с ними вообще не поддерживаются. Базовые фигуры для отсечения тоже не поддерживаются.
Браузеры на основе WebKit, типа Safari и Chrome’а, поддерживают свойства mask-image, mask-box-image и связанные с ними. Все они имеют префиксы и могут применяться только к элементам HTML. Нестабильные версии обоих браузеров уже поддерживают свойство -webkit-clip-path с префиксом в отношении базовых фигур и элементов clipPath в HTML.
Если хотите попробовать отсечение и наложение маски, убедитесь, что применяете свойства с префиксами и без них. Свойства без префиксов в данный момент должны использовать ссылку на mask или clipPath.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<style> #image { mask: url(#mask); -webkit-mask: url(mask.svg) top left / cover; -o-mask: url(mask.svg) top left / cover; -ms-mask: url(mask.svg) top left / cover; } </style> <img id="image" src="coolImage.jpg" width="400"> <svg width="0" height="0"> <mask id="mask"> ... </mask> </svg> |
Но будьте осторожны, у других браузеров еще нет функциональности наложения маски или отсечения для элементов HTML.
Автор: Dirk Schulze
Источник: //www.html5rocks.com/
Редакция: Команда webformyself.