Введение в SVG-фильтры
SVG-фильтры добавляют эффекты к графике. Изучите примитивы фильтров, область фильтра, цепочки и элементы спецификации SVG Filter.
В настоящее время CSS предоставляет возможность применять цветовые эффекты к изображениям (например, яркость, насыщенность, контрастность и т.д.) с помощью свойства filter. Однако CSS-фильтры имеют ограничения. Они предлагают фиксированный набор однофункциональных функций (blur(), brightness(), drop-shadow() и т.д.), которые применяются ко всему элементу и предназначены главным образом для управления цветом и размытием. Для создания более мощных составных эффектов нам понадобятся другие инструменты. Такие инструменты доступны в SVG.
На этой странице рассматривается, что делают SVG-фильтры, элемент <filter> и его область фильтрации, а также то, как примитивы фильтров объединяются в цепочки с помощью механизма in/result.
Что делают SVG-фильтры (и когда их использовать)
SVG-фильтр — это небольшой конвейер обработки изображений. Вместо единственного готового эффекта вы описываете цепочку низкоуровневых операций — называемых примитивами фильтров — где результат одного шага становится входными данными для следующего. Объединяя примитивы в цепочки, можно создавать эффекты, которые CSS не способен выразить самостоятельно:
- Тени и свечения, создаваемые путём смещения, размытия, перекрашивания и повторного наложения исходной графики.
- Текстуры и шум, генерируемые с помощью
<feTurbulence>(шум Перлина) для облаков, бумаги, мрамора и т.д. - Смещение / искажение с помощью
<feDisplacementMap>, который перемещает пиксели, используя другое изображение в качестве карты высот. - Эффекты освещения, которые обрабатывают альфа-канал как трёхмерную карту рельефа.
Когда выбирать SVG-фильтры вместо CSS-фильтров: используйте свойство CSS filter, когда вам нужен быстрый одиночный эффект (размытие, настройка яркости, одна тень) для любого HTML- или SVG-элемента. Обращайтесь к SVG-фильтрам, когда нужно объединить несколько операций в один составной эффект, генерировать текстуры или выполнять смещение — то есть всё то, что требует передачи результата одной операции в другую.
Элемент <filter> и его область
Вы определяете фильтр один раз внутри <defs> и ссылаетесь на него из фигуры с помощью атрибута filter="url(#id)" (или CSS-свойства filter). Сам элемент <filter> ничего не рисует — он является контейнером для примитивов, которые выполняют всю работу.
Фильтр имеет область фильтра: ограничивающий прямоугольник, определяющий, где отображается отфильтрованный результат. Всё, что нарисовано за пределами этой области, обрезается. Область управляется следующими атрибутами элемента <filter>:
| Атрибут | Назначение |
|---|---|
x, y, width, height | Положение и размер области фильтра. По умолчанию: x="-10%", y="-10%", width="120%", height="120%" — то есть отступ по 10% с каждой стороны ограничивающего прямоугольника источника. |
filterUnits | Система координат для x/y/width/height. По умолчанию objectBoundingBox (значения представляют собой доли/проценты от ограничивающего прямоугольника источника); userSpaceOnUse использует абсолютные координаты пространства пользователя. |
primitiveUnits | Система координат для значений длин внутри примитивов (например, dx/dy у feOffset). По умолчанию userSpaceOnUse. |
Эта область — наиболее распространённый источник ошибок. Такие эффекты, как размытие и тени, выходят за пределы исходной фигуры, и стандартная область в 120% нередко оказывается слишком маленькой — тень обрезается по краям. Если ваш эффект выглядит обрезанным, увеличьте область, например: x="-50%" y="-50%" width="200%" height="200%".
Примитивы фильтров
В SVG каждый элемент <filter> включает набор элементов фильтров в качестве дочерних. Каждый примитив фильтра выполняет одну базовую графическую операцию над одним или несколькими входными данными, но выдаёт только один результат. Входные данные указываются в атрибуте in. Результат операции указывается в атрибуте result. Этот результат затем может использоваться как входные данные для других операций. Однако если атрибут in не указан, примитив по умолчанию использует SourceGraphic для первой операции или результат предыдущего примитива в цепочке. Все примитивы имеют одинаковый префикс: fe (сокращение от "filter effect" — «эффект фильтра»). Они именуются в зависимости от того, чем является элемент или что он делает. Например, примитив, применяющий эффект размытия по Гауссу к исходной графике, называется feGaussianBlur.
Специальные ключевые слова для входных данных
Помимо указания result предыдущего примитива, атрибут in может ссылаться на следующие встроенные входные данные:
| Ключевое слово | Значение |
|---|---|
SourceGraphic | Исходный элемент, к которому применяется фильтр, в полном цвете. |
SourceAlpha | Тот же элемент, но только его альфа-канал (прозрачность) — полезен как силуэт для теней. |
BackgroundImage | Снимок холста под элементом. |
BackgroundAlpha | Альфа-канал BackgroundImage. |
FillPaint | Заливка элемента (fill), растянутая на всю область фильтра. |
StrokePaint | Обводка элемента (stroke), растянутая на всю область фильтра. |
Примечание:
BackgroundImage,BackgroundAlpha,FillPaintиStrokePaintвходят в спецификацию, но на сегодняшний день практически не поддерживаются браузерами; на практике вы будете работать сSourceGraphic,SourceAlphaиresultдругих примитивов.
На сегодняшний день существует 17 примитивов фильтров, определённых в спецификации SVG Filter.
Элементы фильтров в SVG
| Элемент | Описание |
|---|---|
<feBlend> | Смешивает два объекта с использованием режимов наложения, распространённых в программах для работы с изображениями. |
<feColorMatrix> | Применяет матричное преобразование. |
<feComponentTransfer> | Выполняет покомпонентное переотображение данных. |
<feComposite> | Выполняет попиксельное объединение двух входных изображений в пространстве изображения. |
<feConvolveMatrix> | Применяет эффект матричной свёртки. |
<feDiffuseLighting> | Освещает изображение, используя альфа-канал в качестве карты рельефа (диффузное освещение). |
<feDisplacementMap> | Использует значения пикселей входного изображения in2 для смещения изображения in. |
<feFlood> | Создаёт прямоугольник, заполненный значениями непрозрачности и цвета из свойств flood-opacity и flood-color. |
<feGaussianBlur> | Применяет размытие по Гауссу к входному изображению. |
<feImage> | Ссылается на внешний графический элемент, который загружается или отрисовывается в RGBA-растр, становящийся результатом примитива. |
<feMerge> | Смешивает слои входных изображений. |
<feMorphology> | Выполняет «сужение» или «расширение». |
<feOffset> | Смещает входное изображение. |
<feSpecularLighting> | Освещает исходную графику, используя альфа-канал в качестве карты рельефа (зеркальное освещение). |
<feTile> | Заполняет целевой прямоугольник повторяющимся паттерном из входного изображения. |
<feTurbulence> | Создаёт изображение с использованием функции турбулентности Перлина. |
<feDropShadow> | Создаёт эффект падающей тени. |
Пример с одним примитивом
Простейший фильтр содержит один примитив. Здесь feGaussianBlur берёт SourceGraphic и размывает его:
<svg width="200" height="200">
<defs>
<filter id="blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="5" />
</filter>
</defs>
<rect x="10" y="10" width="180" height="180" fill="blue" filter="url(#blur)" />
</svg>Цепочка примитивов: падающая тень
Настоящая мощь появляется при использовании цепочек. Чтобы создать падающую тень вручную, мы берём силуэт элемента, смещаем его вниз и вправо, размываем, а затем помещаем исходную графику сверху. Следите за атрибутами result/in, чтобы видеть, как результат каждого шага передаётся в следующий:
<svg width="220" height="220">
<defs>
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
<!-- 1. Take the alpha (silhouette) of the source -->
<feOffset in="SourceAlpha" dx="6" dy="6" result="offset" />
<!-- 2. Blur that offset silhouette -->
<feGaussianBlur in="offset" stdDeviation="4" result="blur" />
<!-- 3. Stack the blurred shadow under the original graphic -->
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<rect x="20" y="20" width="160" height="160" rx="12"
fill="#1e88e5" filter="url(#shadow)" />
</svg>Как передаются данные:
feOffsetчитаетSourceAlpha(силуэт фигуры) и смещает его наdx/dy, записываяresult="offset".feGaussianBlurчитаетin="offset"и смягчает его, записываяresult="blur".feMergeнакладывает слои снизу вверх: сначалаblur(тень), затем размытыйSourceGraphicсверху — так чёткая фигура располагается над мягкой тенью.
Обратите внимание на увеличенную область фильтра (width="140%" height="140%"), чтобы смещённая размытая тень не обрезалась.
Для готовых сокращений смотрите примитив <feDropShadow> и главу об эффектах размытия SVG. Полный список атрибутов для каждого примитива находится в справочнике SVG.