W3docs

Эффекты размытия 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" />

Типичные значения невелики: 13 даёт мягкое смягчение, 510 — явно заметное размытие, а всё, что выше ~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.

Практика

Практика
Каковы функции атрибутов stdDeviation и in в SVG-фильтре 'feGaussianBlur'?
Каковы функции атрибутов stdDeviation и in в SVG-фильтре 'feGaussianBlur'?
Was this page helpful?