この記事の概要
ノイズグラデーション、最近よく見かけますよね。
以下の画像のようなザラっとした質感のグラデーションです。
実はこれ、SVGだけで作れてしまいます。
というわけでその作り方を解説します。
最終形
細かい理屈は良いからとりあえず使いたい!という人は以下をコピペしていただければOKです。
中心からグラデーション
<svg
width="200"
height="200"
viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<filter id="displacementFilter">
<feTurbulence
type="fractalNoise"
baseFrequency="0.8"
numOctaves="3"
result="fractalNoise" />
<feDisplacementMap
in2="fractalNoise"
in="SourceGraphic"
scale="150"
xChannelSelector="R"
yChannelSelector="G" />
</filter>
<mask id="mask">
<circle
cx="100"
cy="100"
r="100"
style="
fill: #FFF;
"
/>
</mask>
<circle
cx="100"
cy="100"
r="100"
style="
fill: #37BCE3;
"
/>
<circle
cx="100"
cy="100"
r="100"
style="
fill: none;
stroke: #003E96;
stroke-width: 40;
filter: url(#displacementFilter);
"
mask="url(#mask)"
/>
</svg>
端からグラデーション
<svg
width="200"
height="200"
viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<filter id="displacementFilter">
<feTurbulence
type="fractalNoise"
baseFrequency="0.8"
numOctaves="3"
result="fractalNoise" />
<feDisplacementMap
in2="fractalNoise"
in="SourceGraphic"
scale="300"
xChannelSelector="R"
yChannelSelector="G" />
</filter>
<mask id="mask">
<circle
cx="100"
cy="100"
r="100"
style="
fill: #FFF;
"
/>
</mask>
<circle
cx="100"
cy="100"
r="100"
style="
fill: #37BCE3;
"
/>
<circle
cx="-25"
cy="225"
r="200"
style="
fill: #003E96;
filter: url(#displacementFilter);
"
mask="url(#mask)"
/>
</svg>
細かな解説
大きく分けて4ステップあります。
- ノイズのもとになる図形を描く
- ノイズをかける
- マスクをかける
- 背景色を追加する
ノイズのもとになる図形を描く
最初のステップは簡単です。
単に円を描いているだけです。
<svg
width="200"
height="200"
viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<circle
cx="100"
cy="100"
r="100"
style="
fill: none;
stroke: #003E96;
stroke-width: 20;
"
/>
</svg>
上記のコードにより、以下のような結果が得られます。
stroke
の仕組み上viewBox
からはみ出てしまっていますが、ここでは問題にならないのでそのままにしておきます。
ノイズをかける
次にノイズをかけます。
<svg
width="200"
height="200"
viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<filter id="displacementFilter">
<feTurbulence
type="fractalNoise"
baseFrequency="0.8"
numOctaves="3"
result="fractalNoise" />
<feDisplacementMap
in2="fractalNoise"
in="SourceGraphic"
scale="150"
xChannelSelector="R"
yChannelSelector="G" />
</filter>
<circle
cx="100"
cy="100"
r="100"
style="
fill: none;
stroke: #003E96;
stroke-width: 40;
filter: url(#displacementFilter);
"
/>
</svg>
現在の見た目はこちらです。
全体的な流れとしては以下です。
- idつきで
filter
を用意する -
filter
内のfeTurbulence
により、ノイズの種類や細かさを指定する -
filter
内のfeDisplacementMap
でfeTurbulence
を受け取り、filter
をかける画像にどのようにかけるかを指定する -
filter
をかけたい要素(今回ならcircle
)のstyle
にfilter: url(#filter-id)
の形式で指定する
それぞれのパラメーターの説明を細かくしようと思うとかなり長くなるのでざっくりとだけ説明します。
-
feTurbulence
-
type
-
fractalNoise
とturbulence
がある - 今回でいうと、座標計算が
fractalNoise
の方がやりやすかったのでこちらを選択
-
-
baseFrequency
- ノイズの細かさで、数値が大きいほど細かいノイズになる
-
numOctaves
- ノイズの複雑さで、数値が大きいほど複雑なノイズになる
-
result
-
feDisplacementMap
に渡す名前の指定
-
-
-
feDisplacementMap
-
in
- 色々な種類の指定があるけど、割と毎回
SourceGraphic
で良いような気がしているので省略
- 色々な種類の指定があるけど、割と毎回
-
in2
-
feTurbulence
から受け取る名前
-
-
scale
- 大きいほどかかり方が強くなる(?)
- これの理解が少し怪しいので、詳しい方がいたら是非コメントで教えてください
- 大きいほどかかり方が強くなる(?)
-
xChannelSelector
|yChannelSelector
- x軸とy軸どちらの座標にどのチャンネルを用いるか
- どちらも同じものを選ばなければ良し、くらいな気がしている
-
MDN Docsには詳しく載っているので、より詳細に知りたい方はこちらをどうぞ。
マスクをかける
ノイズをかけたらかなり広がってしまったので、本来描画したい範囲だけにマスクをかけます。
<svg
width="200"
height="200"
viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<filter id="displacementFilter">
<feTurbulence
type="fractalNoise"
baseFrequency="0.8"
numOctaves="3"
result="fractalNoise" />
<feDisplacementMap
in2="fractalNoise"
in="SourceGraphic"
scale="150"
xChannelSelector="R"
yChannelSelector="G" />
</filter>
<mask id="mask">
<circle
cx="100"
cy="100"
r="100"
style="
fill: #FFF;
"
/>
</mask>
<circle
cx="100"
cy="100"
r="100"
style="
fill: none;
stroke: #003E96;
stroke-width: 40;
filter: url(#displacementFilter);
"
mask="url(#mask)"
/>
</svg>
現在の見た目はこちらです。
ここはグラデーション自体には関係していないので省略します。
背景色を追加する
最後に、背景色を追加します。
<svg
width="200"
height="200"
viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<filter id="displacementFilter">
<feTurbulence
type="fractalNoise"
baseFrequency="0.8"
numOctaves="3"
result="fractalNoise" />
<feDisplacementMap
in2="fractalNoise"
in="SourceGraphic"
scale="150"
xChannelSelector="R"
yChannelSelector="G" />
</filter>
<mask id="mask">
<circle
cx="100"
cy="100"
r="100"
style="
fill: #FFF;
"
/>
</mask>
<circle
cx="100"
cy="100"
r="100"
style="
fill: #37BCE3;
"
/>
<circle
cx="100"
cy="100"
r="100"
style="
fill: none;
stroke: #003E96;
stroke-width: 40;
filter: url(#displacementFilter);
"
mask="url(#mask)"
/>
</svg>
現在の見た目はこちらです。
こちらも、単に同じ色を配置しただけなので説明は省略します。
端から始まる方のグラデーション
実はコードはほとんど変わっていません。
違いは以下の2点だけです。
- strokeにノイズをかけるか、fillにノイズをかけるか
- ノイズをかけた要素をどこに配置するか
そのため、ノイズをかける図形を変えたりサイズを変えればもっと色々な種類が作れます。
最後に
ノイズグラデーションは格好いいので好きなのですが、画像で用意するしかないとなると取り回しがしづらいなあ……と思っていました。
ところが結構簡単にSVGだけで実装できたので、軽いし色を変えるのも簡単だしで、結構良いものが作れた気がします。
あとはsymbol
やuse
を使えばコードとしてももう少し綺麗にできるかもしれません。
そちらも試してみたら記事にしようと思います。
最後まで読んでくださってありがとうございます!
Twitterでも情報を発信しているので、良かったらフォローお願いします!
Devトークでのお話してくださる方も募集中です!