SVGフィルタで拡張するCSSの表現 第1回 SVGフィルタの基本と表現例

SVGフィルタはCSSのfilterプロパティより、複雑な表現が可能です。古くからある技術ですが、活用されることが少ないSVGフィルタの使い方を紹介します。

発行

著者 小山田 晃浩 フロントエンド・エンジニア
SVGフィルタで拡張するCSSの表現 シリーズの記事一覧

はじめに

要素にぼかしや色調変換などの視覚効果を適用したいとき、CSSのfilterプロパティを使うことができます。blur()grayscale()drop-shadow()など、汎用的な関数が用意されています。

CSSのfilterプロパティ

.element {
  filter: blur(5px) grayscale(50%);
}

しかし、CSS Filterの既定関数で実現できる表現には限りがあります。そこで活用できるのがSVGフィルタです。

SVGフィルタは、CSS Filterの表現幅を大きく拡張できます。SVGのfilter要素で定義するフィルタ効果で、さまざまなフィルタ専用のタグを組み合わせて複雑な効果を作成できます。また、CSSのfilterプロパティからurl()関数で呼び出せるため、HTML要素にも適用できます。

SVGフィルタをCSSから呼び出す

.element {
  filter: url(#my-filter);
}

SVGフィルタ自体は古くからある技術で、現在の主要ブラウザでサポートされています。しかし、CSSの標準フィルタ関数と比べて記述が複雑なため、あまり活用されていないのが現状です。本記事では、SVGフィルタの基本と実践的な利用例を紹介します。

シンプルなSVGフィルタの例

まずは基本的なSVGフィルタの構造を見てみましょう。

基本的なSVGフィルタ

<svg style="position: absolute; width: 0; height: 0;">
  <defs>
    <filter id="blur-filter">
      <feGaussianBlur in="SourceGraphic" stdDeviation="3" />
    </filter>
  </defs>
</svg>

filter要素内にフィルタ専用のタグを配置していきます。ここでは<feGaussianBlur>(ガウシアンブラー)というぼかし用のタグを使っています。in属性で元の描画(SourceGraphic)を入力として利用し、stdDeviation属性でぼかしの強さを3に設定しています。結果として、元描画に3pxのぼかしが適用されます。

SVGでフィルタを記述し、それをHTML内に配置します。このとき、SVG自体は表示したくないので、style="position: absolute; width: 0; height: 0;"でSVG要素をCSSで非表示にしておきます。

filter要素にはidを付けておき、CSSからはこのidを参照してフィルタを適用します。

CSSでの適用

.filtered {
  filter: url(#blur-filter);
}

なお、CSSは外部ファイルでも問題ありませんが、SVGはフィルタを適用する要素と同じHTML内に記述する必要があります(Safari以外は外部SVGでも可能です)。

ブラウザ上では次のように表示されます。なお、本記事のデモでは、すべて上にSVGフィルタ適用前、下にSVGフィルタ適用後の例を示しています。

in属性の値について

今回の解説では、in属性の値として以下が登場します。

  • SourceGraphic
  • SourceAlpha
  • フィルタープリミティブのresultで定義した値(任意の値)

SVGフィルタのin属性には、これら以外にも以下の4種類が定義されています。ただし、ブラウザではサポートされておらず実際には使用できません。

内容
BackgroundImage 背景(フィルター適用前の背後にある内容)
BackgroundAlpha 背景のアルファチャンネル
FillPaint 塗り(fill)として使われているペイント
StrokePaint 線(stroke)として使われているペイント

SVGフィルタの主要なタグ

filter要素内で使用できる主要なタグを紹介します。これらはフィルタ専用のタグで、fe(filter effectの略)から始まる名前が付けられています。

タグ 効果
feGaussianBlur ガウシアンぼかし
feDisplacementMap ピクセルの変位による歪み
feTurbulence パーリンノイズの生成
feConvolveMatrix 畳み込み演算(コンボリューション行列。エッジ検出など)
feMorphology 膨張・収縮
feOffset 位置のオフセット
feFlood 単色で塗りつぶし
feColorMatrix 色変換(マトリックス演算)
feComposite 2つの入力の合成
feBlend 2つの入力のブレンド
feMerge 複数の入力を重ねて合成

これらを組み合わせることで、さまざまな視覚効果を作成できます。

SVGフィルタの表現例

SVGフィルタで実現できる表現の例として、10種類の効果を紹介します。SVGフィルタは本来、SVG要素に対してのみ適用できますが、CSSを介して適用すれば、テキストにも画像にも、あるいはdiv丸ごとにもフィルタを適用できます。

まずはあまりコードは気にせずに、「どんな表現ができるか」をざっと見てみてください。もちろん、気になる表現があればデモの「ソースコード」からコードを見ることができます。もし気に入った効果があれば、個人・商用問わず、コードをコピーして自由に自身で利用してかまいません。

1. 色の乗算

feFloodで色を生成し、feBlendmultiplyモードで元描画と合成します。feCompositeでアルファチャンネル部分に適用することで、元描画の不透明部分にのみ色を乗せることができます。

2. 縦方向のみぼかし

CSSのblur()関数はX方向とY方向のぼかしを同時に適用しますが、SVGフィルタは単方向のみにぼかしを適用できます。

feGaussianBlurstdDeviation属性は、スペース区切りで2つの値を指定できます。stdDeviation="0 4"とすると、X方向は0、Y方向は4のぼかしになります。

3. グロー(発光)

元描画をぼかして発光部分を作り、feColorMatrixで色を変換してから元描画と重ねます。ネオンサインのような効果が得られます。SVGフィルタは、フィルタ適用前の描画とフィルタ効果自体を別々に保持できるからこそできる表現です。

4. 色収差

レンズの収差を模倣した効果です。RGBチャンネルをそれぞれ異なる方向にオフセットして合成します。

5. ノイズでくり抜き

feTurbulenceでノイズを生成し、feComponentTransferでコントラストを上げます。そのノイズをアルファチャンネルとして使用することで、粒子状にくり抜く効果を作成しています。

6. 歪ませる

feTurbulenceでノイズを生成し、feDisplacementMapでそのノイズに基づいて画像を歪ませます。

7. スケッチ(手書き風)

上記と同様ですが、feTurbulenceで生成したノイズをfeDisplacementMapで微小に歪ませることで、手書きのような揺れを表現します。

8. 炎

feTurbulenceで縦長のノイズを生成し、feDisplacementMapで歪ませます。アルファチャンネルをコピーして異なる色(黄色、赤)で着色し、上方向にオフセットして重ねることで、炎が立ち上るような表現を作成できます。animate要素でscale値をアニメーションさせると、メラメラと燃える動きも表現できます。

9. 水面

複数のfeTurbulenceノイズを生成し、それぞれをfeOffsetで異なる方向にアニメーションさせます。2つの横方向のノイズをfeCompositeで合成し、合成したノイズを使ってfeDisplacementMapで歪ませることで、水面のゆらめきのような効果を作成できます。animate要素を使うとSafariではCPUにやや高い負荷がかかります。さらにこのデモではanimate要素を2つ使っているため、Safariでは高負荷・低FPSで動作します。

10. 電気

高周波のfeTurbulenceで細かいノイズを生成し、feDisplacementMapでギザギザに歪ませます。feColorMatrixで青白い電気色に変換し、feGaussianBlurでグローを追加。<animate>でノイズとスケールを高速に変化させることで、ビリビリと放電するような効果を表現します。

基本的な適用の流れ

SVGフィルタは、次の流れで効果を適用します。ここまで紹介した10種類の表現も、作り方を分解すると、すべて「入力→効果→合成」という同じ基本パターンで説明できます。

  1. 入力:HTMLの描画結果(SourceGraphic)、またはそのアルファチャンネル(SourceAlpha)をフィルタに入力する
  2. 効果:入力に対してフィルタ効果を適用する。複数の効果を組み合わせることもできる
  3. 合成:入力やフィルタ結果を合成して最終的な出力を作成する

SVGフィルタには、操作元の情報(ソース)としてSourceGraphicSourceAlphaの2種類を扱えます。

  • SourceGraphic:元の描画の色を使って操作したいとき
  • SourceAlpha:元の描画の形状や範囲を利用して操作したいとき

たとえば、枠線を追加するフィルタの場合は次のような処理になります。

  1. 入力:アルファチャンネル(SourceAlpha)を入力
  2. 効果feMorphologyでアルファチャンネルを膨張させる
  3. 合成feMergeで膨張したアルファの上に元の描画(SourceGraphic)を重ねる

枠線を追加するフィルタの処理

<svg style="position: absolute; width: 0; height: 0;">
  <defs>
    <filter id="outline-filter">
      <!-- 元のアルファチャンネルを膨張させる -->
      <feMorphology in="SourceAlpha" operator="dilate" radius="4" result="dilated" />
      <feMerge>
        <!-- アルファチャンネルを膨張させた塗りと、元画像の塗りを重ねる -->
        <feMergeNode />
        <feMergeNode in="SourceGraphic" />
      </feMerge>
    </filter>
  </defs>
</svg>

この「入力→効果→合成」の流れを意識すると、フィルタの構造が理解しやすくなります。

そして、できあがったフィルタのidをCSSのfilterプロパティで呼び出すことで、HTML要素に効果を適用できるわけです。

CSSでの適用

.element {
  filter: url(#outline-filter);
}

今回は、SVGフィルタの基本的な構成とその表現例を見てみました。次回はSVGフィルタの基本操作として、色を制御する方法を見ていきます。