LoginSignup
38
28

SVG だけで作るノイズ & フリーフォームグラデーション

Posted at

この記事の概要

2023 年 8 月 20 日開催のなごデ LT という LT イベントで発表する内容です。

Grainy Gradient1 と調べると、ザラっとした質感でフリーフォームなグラデーションが出てきます。

こういった表現をデジタルプロダクトで実施しようと思うと、どうしても画像に頼りがちです。
画像で作ると、少しだけ色を変えたいときに毎度画像ごと編集する必要があり手間がかかります。
また、ワンポイントで使うならいざしらず、背景全面に敷こうなどとすれば結構なファイルサイズ2になりそうで好ましくありません。

というわけで、サイズの軽い svg で実現してみせようという記事です。

作ったもの

ディスプレイに大きく表示しないと分かりづらいので GitHub Pages で公開しました。

背景画像だけを抜き出すとこんな感じです。

色の違いが分かりやすいようなグラフィックにしたつもりですが、実際は様々な色や形状で作れます。

作り方

コードの全体像

<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"> <!-- 1. 好きな viewBox のサイズ -->
  <g filter="url(#noise)"> <!-- 3. filter の用意 -->
    <!-- 2. 色々なパス -->
  </g>
  <defs>
    <filter id="noise"> <!-- 3. filter の用意 -->
      <feTurbulence baseFrequency="1" numOctaves="1" stitchTiles="stitch" type="fractalNoise" result="turbulence"/> <!-- 3.1. feTurbulence -->
      <feGaussianBlur in="SourceGraphic" stdDeviation="64 8" result="blur"/> <!-- 3.2. feGaussianBlur -->
      <feBlend mode="color-burn" in="turbulence" in2="blur"/> <!-- 3.3. feBlend -->
    </filter>
  </defs>
</svg>

1. 好きな viewBox のサイズ

見本では viewBox="0 0 1024 1024" としていますが、基本的にどんなサイズでも構いません。
ただし、実際に表示する際の幅や高さとあまりにもかけ離れたサイズを指定すると、綺麗なノイズが出ないなどの問題が起き得ます。

大きければ大きいほど良い、というものでもないので、ほどほどのサイズで指定しておきましょう。

<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
</svg>

2. 色々なパス

この領域に自分の好きな色・形のパスを用意します。
今回はこんなものを用意しました。

正直言うと、どうしても後から色々微調整する必要はあるので、この段階で神経質になる必要はありません。

ここまでのコードは次のようになります。

  <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
+   <g>
+     <!-- 色々なパス -->
+   </g>
  </svg>

3. filter の用意

先ほど作ったパスにノイズやぼかしを加えるためには filter を使います。

今回は 1 つしか用意していませんが、複数のフィルターを用意して、それぞれのパスで filter="url(#noise1)", filter="url(#noise2)", filter="url(#noise3)" のように適用することも可能です。

ここまでのコードは次のようになります。

  <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
-   <g>
+   <g filter="url(#noise)">
      <!-- 色々なパス -->
    </g>
+   <defs>
+     <filter id="noise">
+     </filter>
+   </defs>
  </svg>

3.1 feTurbulence

フラクタルノイズやタービュレントノイズを作れます。
色々な設定ができますが、次のような内容をおすすめします。

  • baseFrequency
    • 0.8 - 1.2 程度
  • numOctaves
    • 1 - 3 程度
  • stitchTiles
    • stitch
  • type
    • fractalNoise

組み合わせ方によって大きく見た目が変わるので、詳細が気になる人は MDN Docs などをどうぞ。

ここまでのコードは次のようになります。
feTurbulence の中に result という属性があり、ここまでノータッチですが、後から説明します。)

  <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
    <g filter="url(#noise)">
      <!-- 色々なパス -->
    </g>
    <defs>
      <filter id="noise">
+       <feTurbulence baseFrequency="1" numOctaves="1" stitchTiles="stitch" type="fractalNoise" result="turbulence"/>
      </filter>
    </defs>
  </svg>

現段階での見た目は次のようになります。
……先ほど作成したパスがすべて消えて、あたり一面のノイズになってしまいましたが、大丈夫です。

3.2 feGaussianBlur

ガウスぼかしをかけられます。

in="SourceGraphic" を指定した場合、元々の画像をぼかす、と考えてもらえれば大丈夫です。

stdDeviation はぼかし半径です。
ただ、水平ぼかし量と垂直ぼかし量をそれぞれ設定できます。
別の値を設定しておいた方がより表情豊かな見た目になると思います。

今回は stdDeviation="64 8" と設定しました。

こちらも詳細が気になる人は MDN Docs などをどうぞ。

ここまでのコードは次のようになります。

  <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
    <g filter="url(#noise)">
      <!-- 色々なパス -->
    </g>
    <defs>
      <filter id="noise">
        <feTurbulence baseFrequency="1" numOctaves="1" stitchTiles="stitch" type="fractalNoise" result="turbulence"/>
+       <feGaussianBlur in="SourceGraphic" stdDeviation="64 8" result="blur"/>
      </filter>
    </defs>
  </svg>

現段階での見た目は次のようになります。
ぼかしがかかった代わりにノイズが完全に消滅しましたが、これも現段階では大丈夫です。

3.3 feBlend

ここまで、ノイズだけになったりぼかしだけになったりで、狙った通りの見た目になりませんでした。
今回の feBlend を使うことで解消します。

見本のコードで書かれるだけ書かれていて触れられていなかった result とともに解説します。

feBlend には inin2 という属性があり、この 2 つに渡した内容をブレンドします。
ブレンドの方法は CSS の mix-blend-mode と同じです。
今回は color-burn を選びましたが、overlay でも hard-light でもお好きなものをどうぞ。

こちらも詳細が気になる人は MDN Docs などをどうぞ。

ここまでのコードは次のようになります。

  <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
    <g filter="url(#noise)">
      <!-- 色々なパス -->
    </g>
    <defs>
      <filter id="noise">
        <feTurbulence baseFrequency="1" numOctaves="1" stitchTiles="stitch" type="fractalNoise" result="turbulence"/>
        <feGaussianBlur in="SourceGraphic" stdDeviation="64 8" result="blur"/>
+       <feBlend mode="color-burn" in="turbulence" in2="blur"/>
      </filter>
    </defs>
  </svg>

これで、最初に示したのと同じ見た目になりました。

最後に

見本では簡単めなコードにしましたが、複数の feBlend を組み合わせて更に複雑な表情を作ることも可能です。

ちなみに、似たような内容で以前こんな記事も書きました。
こちらもあわせて読んでいただけたら嬉しいです。


最後まで読んでくださってありがとうございます!
X (Twitter)でも情報を発信しているので、良かったらフォローお願いします!

Devトークでお話してくださる方も募集中です!

  1. 「グレイニーグラデーション」と記載してもあまりにも馴染みがなさそうだったので、タイトルでは「ノイズ & フリーフォームグラデーション」としています。

  2. 試しに、高解像度ディスプレイでも荒れないくらいのサイズで作ったら jpg ですら 数 MB になってしまいました。更に png では 10 MB を超えました。嫌すぎます。

38
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
28