PerfectVector
Автор: Irene Kim7 мин чтения

SVG clipPath и mask: чёткие края или плавное затухание

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

На этой странице

Используйте SVG <clipPath>, если изображение должно заканчиваться по заданному контуру. Используйте SVG <mask>, если оно должно плавно исчезать через частичную прозрачность. Маска также может сделать резкую границу, но контур обрезки проще выражает намерение получить чёткий геометрический край. Спецификация CSS Masking определяет их как отдельные операции видимости.

Выбор важен, когда изображение в форме логотипа отправляется в другой редактор. Оба метода управляют тем, что вы видите; ни один не превращает скрытые пиксели в удалённую геометрию и не преобразует изображение в векторные контуры. Это руководство использует одну собственную растровую сцену и один контур, меняя только правило видимости. Перед экспортом вы можете применить тот же тест к своей графике.

Выбирайте по нужному краю

ЦельС чего начатьЧто управляет видимостьюЧто проверить перед передачей
Обрезать изображение по чёткому контуру логотипа или значка<clipPath>Нахождение внутри или вне контураСовмещение контура и сохранение обрезки в целевом приложении
Плавно скрыть изображение к краю<mask mask-type="alpha">Непрозрачность графики маскиПрозрачные точки градиента, область маски и цвет фона
Использовать бело-чёрную графику для затухания<mask mask-type="luminance">Яркость, умноженная на непрозрачностьТёмные области, прозрачные области и область маски
Получить постоянные обрезанные векторные контурыРедактирование контуров или операция пересеченияСами результирующие контурыОткрыть и проверить контуры в целевом приложении

Видимый край обрезки всё ещё может иметь обычное сглаживание отрисовки. Но обрезка не может выразить намеренную полосу частичной видимости от градиента оттенков серого или непрозрачности внутри обрезанной фигуры. Урок MDN по обрезке и маскированию показывает это различие на небольших примерах SVG.

Сравните одно изображение при трёх правилах видимости

Для этого теста я нарисовала небольшой пейзаж, растеризовала его в PNG 400 × 240 и поместила те же пиксели под один и тот же листообразный контур в каждой панели. Левая панель обрезает изображение по этому контуру. Средняя использует бело-чёрную маску яркости; правая — альфа-маску от непрозрачного к прозрачному. Оба градиента подобраны для одинакового затухания слева направо. Каждый результат показан на светлом и тёмном фоне, что облегчает оценку исчезающего края.

Собственное сравнение SVG: один пейзаж внутри чёткого контура обрезки, маски яркости в оттенках серого и альфа-маски непрозрачности, каждый на светлом и тёмном фоне
Собственный тестовый SVG, отрисованный через Sharp. Обрезка сохраняет чёткий контур; маски яркости и альфа-маски дают похожее затухание, поскольку их градиенты специально подобраны для одинаковой видимости. Это пример отрисовки, а не результат преобразования PerfectVector.

Два столбца масок похожи по определённой причине: бело-чёрный градиент яркости и градиент непрозрачности белого кодируют сопоставимые значения маски. Их исходные данные не взаимозаменяемы. Непрозрачный чёрный скрывает при маскировании яркостью, но остаётся видимым при альфа-маскировании. В режиме альфа результат определяет непрозрачность пикселя, а не его чёрный или белый цвет. Определение обработки масок CSS Masking задаёт оба расчёта.

Постройте обрезку и маску по одному контуру

Сохраните следующий код как clip-or-mask.svg, поместите рядом свой photo.png и предоставьте оба файла из одной папки через HTTP. Два изображения используют одну систему координат 400 × 240. Они различаются лишь clip-path и mask.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 280">
  <defs>
    <path id="motif"
      d="M30 175 C65 82 140 28 232 41 C290 44 304 75 374 39
         C361 122 310 196 236 219 C139 246 75 217 30 175 Z" />
 
    <clipPath id="hard" clipPathUnits="userSpaceOnUse">
      <use href="#motif" />
    </clipPath>
 
    <linearGradient id="fade" x1="0" y1="0" x2="1" y2="0">
      <stop offset="0" stop-color="white" stop-opacity="1" />
      <stop offset=".45" stop-color="white" stop-opacity="1" />
      <stop offset="1" stop-color="white" stop-opacity="0" />
    </linearGradient>
    <mask id="soft" mask-type="alpha" maskUnits="userSpaceOnUse"
      maskContentUnits="userSpaceOnUse" x="0" y="0" width="400" height="240">
      <use href="#motif" fill="url(#fade)" />
    </mask>
  </defs>
 
  <g transform="translate(20 20)">
    <image href="photo.png" width="400" height="240"
      clip-path="url(#hard)" />
  </g>
  <g transform="translate(440 20)">
    <image href="photo.png" width="400" height="240"
      mask="url(#soft)" />
  </g>
</svg>

Ссылочные ID должны быть уникальны внутри SVG. И область обрезки, и маска используют userSpaceOnUse, чтобы координаты мотива совпадали с локальной областью 400 × 240 каждого изображения. Справочник MDN по <clipPath> описывает обрезку как ограничение рисования без изменения собственной геометрии цели. Справочник MDN по <mask> разделяет maskUnits, задающий положение области маски, и maskContentUnits, задающий положение её графики.

Чтобы попробовать яркость, создайте копию маски с другим ID, установите mask-type="luminance" и измените точки градиента на непрозрачный белый в начале и непрозрачный чёрный в конце. Согласуйте ссылку mask с новым ID. По умолчанию SVG <mask> использует яркость; этот пример явно называет режим, чтобы будущая правка не изменила незаметно смысл чёрного. См. справочник MDN по mask-type.

Проверьте результат перед экспортом

  1. Отрисуйте SVG на светлом и тёмном фоне. Затухание, незаметное на белом, может быть очевидным на тёмном.
  2. Убедитесь, что изображение и мотив используют одинаковые координаты. Если изменить размер только изображения, контур может перестать совпадать. Для повторно используемых областей обрезки на целях разного размера руководство по единицам clipPath объясняет варианты координат.
  3. Если мягкий край обрывается резко, проверьте x, y, width и height маски вместе с градиентом. Область маски может обрезать графику за своими границами; расширение одного градиента не исправит узкую область. MDN перечисляет значения по умолчанию области маски, но явные границы легче проверять в передаваемом файле.
  4. Заново откройте сохранённый SVG в приложении, где он будет использоваться. Правильная отрисовка в браузере не подтверждает, что другой импортёр сохранит обрезку, маску, связанное изображение или нужную редактируемость.
  5. Проверьте структуру файла. Если он всё ещё содержит <image>, в нём остаются растровые пиксели, хотя контур обрезки векторный. Проверка встроенного растра показывает, как заметить это различие.

Изображение в этом примере остаётся PNG. Обрезка и маскирование его не трассируют. Если задача требует реальной геометрии резки или постоянного прозрачного отверстия, создайте соответствующие контуры в редакторе и проверьте экспорт. Руководство по заполняющимся отверстиям помогает отличить настоящее отверстие от белого пятна, которое лишь выглядит пустым на белом холсте.

Где пригодится PerfectVector

Если нужный контур сохранился только в PNG- или JPG-логотипе, процесс преобразования изображения в вектор PerfectVector может дать редактируемый вариант SVG. Проверьте внешний контур, небольшие промежутки и нежелательные фоновые фигуры, прежде чем копировать контур в <clipPath> или <mask>. Метод видимости и построение эффекта в редакторе SVG всё ещё выбираете вы. Если есть качественный векторный оригинал, сохраняйте его.

Не нужно векторизовать фотографию только для помещения за маской. Оставьте фотографические пиксели изображением, если сохранение деталей важно. Для одноцветной иконки, управляемой CSS, а не изображения внутри SVG, руководство по CSS-маскам SVG описывает отдельный процесс.

Частые вопросы

Может ли SVG clipPath создать плавное затухание? Нет. Контур обрезки определяет видимые части цели, помимо обычного сглаживания на границе. Для намеренного затухания используйте маску с промежуточными значениями непрозрачности или яркости.

Чёрный скрывает изображение в любой маске SVG? Нет. Непрозрачный чёрный скрывает при маскировании яркостью, но показывает при альфа-маскировании, поскольку пиксель остаётся непрозрачным. Полностью прозрачная графика скрывает в обоих режимах.

Превращает ли обрезка или маскирование PNG в векторную графику? Нет. Оба меняют видимость во время отрисовки. SVG всё ещё может содержать растровый <image> и требовать отдельной трассировки или редактирования контуров для полностью векторного файла.

Источники

  1. W3C — CSS Masking Module Level 1 — Определения обрезки, маскирования и значений альфа-масок и масок яркости.
  2. MDN — Clipping and masking — Примеры чёткой обрезки и мягких масок.
  3. MDN — <clipPath> — Поведение обрезки, выбор координат и неизменность исходной геометрии.
  4. MDN — <mask> — Область маски, система координат содержимого и поведение ссылок.
  5. MDN — mask-type — Альфа-интерпретация и интерпретация яркости графики маски SVG.

Если растровому логотипу сначала нужны редактируемые контуры, создайте вариант SVG с PerfectVector, проверьте восстановленный контур, затем примените обрезку или маску и заново откройте экспортированный файл в целевом приложении.

Ещё из блога

Начните с более чистого SVG,
который проще редактировать