Эффекты размытия SVG
SVG предлагает различные функции для создания мощных эффектов изображений. Узнайте о примитивах фильтров, элементах SVG <defs> и <filter>.
На этой странице рассматривается, как размывать SVG-графику с помощью примитива фильтра <feGaussianBlur>: как управлять степенью размытия, как размывать только силуэт фигуры, как задавать размер области фильтра, чтобы размытие не обрезалось, и когда лучше использовать более простое CSS-свойство filter: blur().
Описание SVG-фильтров
Все SVG-фильтры определяются внутри элемента <defs>. <defs> — это сокращение от definitions (определения). Он содержит многократно используемые элементы — например, фильтры — которые не отображаются до тех пор, пока на них не будет сделана ссылка.
Элемент <filter> определяет SVG-фильтр. Ему необходим атрибут id (обязательный), который идентифицирует фильтр. Элемент <filter> не отображается напрямую: он вступает в действие только при обращении через атрибут filter фигуры SVG или через функцию url() в CSS.
Каждый элемент <filter> содержит один или несколько примитивов фильтра в качестве дочерних элементов. Примитив фильтра выполняет одну графическую операцию над одним или несколькими входными данными и возвращает единственный результат. Помимо использования результата другого примитива в качестве входных данных, примитив может также принимать встроенные источники, такие как SourceGraphic и SourceAlpha.
Каждый примитив фильтра использует префикс fe, который расшифровывается как «filter effect» (эффект фильтра). В спецификации SVG Filter определено 17 примитивов фильтра. Для размытия элемента используется <feGaussianBlur>.
Пример создания эффекта размытия:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<svg width="150" height="150">
<defs>
<filter id="filter" x="0" y="0">
<feGaussianBlur in="SourceGraphic" stdDeviation="20" />
</filter>
</defs>
<rect width="110" height="110" stroke="green" stroke-width="5" fill="lightblue" filter="url(#filter)" />
Sorry, your browser doesn't support inline SVG.
</svg>
</body>
</html>Пояснение кода:
- Атрибут
idэлемента<filter>задаёт уникальное имя фильтра. - Эффект размытия создаётся элементом
<feGaussianBlur>. in="SourceGraphic"передаёт всю фигуру — вместе с цветами — на вход фильтра размытия.stdDeviationзадаёт интенсивность размытия.- Атрибут
filterэлемента<rect>связывает фигуру с фильтром по егоid.
Атрибут stdDeviation
stdDeviation управляет степенью размытия. Это стандартное отклонение функции Гаусса, применяемой к пикселям — проще говоря, чем больше значение, тем шире область воздействия на каждый пиксель и тем мягче выглядит изображение. 0 означает отсутствие размытия.
Можно указать одно значение для равномерного размытия или два значения, разделённых пробелом, для асимметричного размытия, при котором оси X и Y размываются на разные величины:
<!-- Uniform blur in both directions -->
<feGaussianBlur in="SourceGraphic" stdDeviation="5" />
<!-- 20px of horizontal blur, 5px of vertical blur (motion-blur look) -->
<feGaussianBlur in="SourceGraphic" stdDeviation="20 5" />Типичные значения невелики: 1–3 даёт мягкое смягчение, 5–10 — явно заметное размытие, а всё, что выше ~20, делает фигуру практически неузнаваемой. Поскольку размытие распространяется во все стороны, оно выходит за пределы исходных границ фигуры — именно поэтому важна область фильтра (см. ниже).
SourceGraphic и SourceAlpha
Атрибут in определяет, с чем работает примитив. Два встроенных источника ведут себя очень по-разному:
in="SourceGraphic"— элемент в том виде, в котором он нарисован, включая заливку, обводку и цвета. Размытие этого источника даёт мягкую полноцветную копию фигуры.in="SourceAlpha"— только альфа-канал (прозрачность) элемента. Информация о цвете отбрасывается, оставляя сплошной чёрный силуэт фигуры. Размытие этого источника лежит в основе эффекта тени, поскольку для него нужен бесцветный размытый контур, смещённый позади оригинала. Подробнее см. тени в SVG.
<!-- Soft, full-color blur -->
<feGaussianBlur in="SourceGraphic" stdDeviation="6" />
<!-- Blurred black silhouette (colors removed) -->
<feGaussianBlur in="SourceAlpha" stdDeviation="6" />Область фильтра (x, y, width, height)
У элемента <filter> есть область отсечения. По умолчанию она составляет x="-10%" y="-10%" width="120%" height="140%" от ограничивающего прямоугольника элемента — отступ 10% с каждой стороны. Сильное размытие легко выходит за этот отступ, и всё, что оказывается за пределами области, обрезается с жёстким краем, из-за чего создаётся ощущение резкого обрыва.
Атрибуты x, y, width и height элемента <filter> задают эту область. В первом примере x="0" y="0" смещает верхний левый угол области к началу координат элемента. Чтобы дать сильному размытию место для плавного затухания, увеличьте область:
<filter id="soft" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur in="SourceGraphic" stdDeviation="15" />
</filter>Если размытие выглядит обрезанным с одной стороны, как правило, область фильтра слишком мала — увеличьте её.
Цепочка примитивов с помощью result
Когда фильтр содержит несколько примитивов, атрибут result присваивает имя выходным данным примитива, чтобы следующий примитив мог обратиться к ним через in. Так соединяются многоэтапные эффекты (размытие, затем смещение, затем объединение):
<filter id="chain">
<feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blurred" />
<feOffset in="blurred" dx="3" dy="3" />
</filter>Здесь feGaussianBlur сохраняет размытый силуэт под именем blurred, а feOffset считывает его с помощью in="blurred". Без связки result/in каждый примитив просто снова размывал бы исходный источник.
Размытие изображения и текста
<feGaussianBlur> работает с любым содержимым SVG, а не только с прямоугольниками. В примере ниже один и тот же фильтр размывает встроенное изображение и строку текста. Область фильтра увеличена, чтобы размытие не обрезалось по краям.
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<svg width="320" height="240">
<defs>
<filter id="blurFilter" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur in="SourceGraphic" stdDeviation="4" />
</filter>
</defs>
<image
href="https://www.w3docs.com/build/assets/images/logo.svg"
width="180" height="60" x="20" y="20"
filter="url(#blurFilter)" />
<text x="20" y="160" font-size="40" fill="navy" filter="url(#blurFilter)">
Blurred text
</text>
Sorry, your browser doesn't support inline SVG.
</svg>
</body>
</html>Альтернатива — CSS filter: blur()
Для быстрого размытия HTML-элемента (или целого SVG) CSS предлагает гораздо более простую функцию filter: blur():
img {
filter: blur(4px);
}filter: blur() принимает одно значение длины и применяет равномерное гауссово размытие — это наилучший выбор, когда нужно просто смягчить элемент. Используйте SVG-подход с <feGaussianBlur>, когда требуется:
- Асимметричное размытие (разные значения по X и Y через
stdDeviation="20 5"). - Размытие только силуэта (
in="SourceAlpha"). - Объединение размытия с другими примитивами — смещениями, цветовыми преобразованиями, слиянием — для создания таких эффектов, как тени.
- Повторно используемый именованный фильтр, на который ссылаются несколько фигур.
Полный список примитивов фильтра и атрибутов см. в справочнике SVG.