liquid-glassをSVGで作ってみる
最近Appleが発表した新しいデザイン素材、LiquidGlassが話題になっています
こういうものらしい↓
新しい素材であるLiquid Glassは、半透明で、実世界のガラスのような挙動を示します。その色は周囲のコンテンツによって決まり、明るい環境と暗い環境との間でインテリジェントに適応します。
Xを眺めているとこのLiquidGlassを模したエフェクトをWebで表現する試みが色々あり、面白そうだなと思って自分も真似してみることにしました。
というわけでこの記事は、諸兄のcodepenやsandboxを拝見しながら似たようなものを自分なりに作った際の備忘録です。
作ったもの
リポジトリ
code sandbox
ホバーすると中身が展開するプログレスUIを題材にしてみた。プログレスUIのインタラクティブも含めて、HTML+CSSのみで作成してます。
ちなみに背景画像はGeminiに作ってもらった。
やったこと
やっていることとしては、SVGフィルターでエフェクトを作る→それをCSSから参照して適用する、これだけです。(その他諸々の微調整もありますが、そのあたりは好きにやったらよいと思われ)
以下に重要な部分の手順を示します。
1. SVGフィルターでliquid-glass風のエフェクトを作る
SVGにはノイズや歪みを発生させるフィルターが用意されており、それらを組み合わせるとliquid-glass風のエフェクトを得ることができます。
以下に、今回作成したフィルターの実装とその説明を簡単にまとめています。
それぞれの設定値を完全に理解できてるわけではなく、見た目がそれっぽくなるようにフィーリングで値をいじっていったら以下のような値になったという感じです。
SVGフィルター
<!-- <svg>要素自体は表示させないので、`display:none`を設定しておく -->
<svg style="display: none">
<defs>
<!-- 液体ガラスのような歪み効果を作るフィルター -->
<filter id="lg-dist" x="0%" y="0%" width="100%" height="100%">
<!-- フラクタルノイズを生成 - ランダムな模様の基となる -->
<feTurbulence
type="fractalNoise" <!-- フラクタルノイズタイプ(より自然な模様) -->
baseFrequency="0.004 0.004" <!-- ノイズの細かさ(小さいほど大きな模様) -->
numOctaves="1" <!-- オクターブ数(複雑さのレベル) -->
seed="0" <!-- 乱数のシード値(同じ模様を再現) -->
result="noise" <!-- この結果を"noise"として参照 -->
/>
<!-- ノイズをぼかしてなめらかにする -->
<feGaussianBlur
in="noise" <!-- 入力:上で作った"noise" -->
stdDeviation="8" <!-- ぼかしの強さ(大きいほどぼける) -->
result="blurred" <!-- この結果を"blurred"として参照 -->
/>
<!-- 色の合成処理(明度や色調を調整) -->
<feComposite
operator="arithmetic" <!-- 算術演算による合成 -->
k1="0" <!-- 入力1×入力2の係数 -->
k2="1" <!-- 入力1の係数 -->
k3="2" <!-- 入力2の係数(2倍で明るく) -->
k4="0" <!-- 定数項 -->
result="litImage" <!-- この結果を"litImage"として参照 -->
/>
<!-- 最終的な歪み効果を適用 -->
<feDisplacementMap
in="SourceGraphic" <!-- 入力:元の画像 -->
in2="litImage" <!-- 歪みマップ:上で作った"litImage" -->
scale="-40" <!-- 歪みの強さ(負の値で内側に歪む) -->
xChannelSelector="G" <!-- X方向の歪みにGreen成分を使用 -->
yChannelSelector="G" <!-- Y方向の歪みにGreen成分を使用 -->
/>
</filter>
</defs>
</svg>
2.SVGフィルターをCSSから参照する
作成した<filter>要素への参照(id名)を、CSSのbackdrop-filter
に設定します。
これで要素の背景に対してエフェクトを適用することができるようになります。
.liquidGlass-effect {
position: absolute;
inset: 0;
content: "";
z-index: -1;
backdrop-filter: url(#lg-dist); <!-- ここでフィルターを適用 -->
isolation: isolate;
}
感想
- SVGフィルター面白い
- もっとliquid-glass感のあるエフェクトが得たい場合は、JSを使うかおとなしくWebGLに頼るのがよさそう
- WebGLでも試してみたい
- 俺はけっこう好きかもしれない
- ぐにゃぐにゃしているので人によっては不快感がありそうだとも思った
得た知見
- SVGのフィルターで、「それっぽい」ものを作ることはできるが、魚眼レンズのような綺麗な歪みは得られない
- エフェクトにザラツキがある、若干カクつく、ジャンク的挙動がみられることがあるので、レンダリングパフォーマンスには注意が必要
- liquid-glasエフェクトを適用する要素の透明度の調整が難しい。テキストの可読性担保するのむずい
Discussion