SVGでニューモフィズムの
アニメーション。

〽️仕組みを考える。 〽️画像作成。 〽️周りと調和した配色。 〽️凹みver。 〽️ニューモフィズムをアニメーション。 〽️長くなりました💧





⬆︎SVGついてのまとめページ、CSSアニメーションの基本コーナーはこちら。

こんにちは、「ふ」です。
今回はSVGを使って、webデザインのトレンドとなっている(過ぎつつある?)、「ニューモフィズム」を作ってみたいと思います。ついでに動かします。

ニューモフィズムデザインとは、要素が背景から押し出された、あるいは凹んだような表現方法です。
HTML要素にニューモフィズムを施すには、CSSのbox-shadowを利用したものが多く見受けられますが、SVG要素にニューモフィズムもどき(笑)を施すにはどうすればいいのでしょうか? ちょっと工夫が必要でした。

「背景に対して凹んでいる、浮き出ている表現」ということで、配色は背景に馴染ませる必要がありました。周りと調和した色の指定法についても紹介します。

仕組みを考える。


先づはニューモフィズムの仕組みを調査してきました。

ニューモフィズムには「出っ張り」と「凹み」の2つのパターンがあるようです。 ネットで色々なサンプルを観察してみると、要素に対し「光となる成分」と「影となる成分」の両方を、対角線上に落としていることがわかりました。
通常のHTML要素に対して実装する場合では、CSSのbox-shadowを使って「明るい色の影・暗い色の影」の2つを施しているようです。

そして影の位置によって、「出っ張り」「凹み」をきりかえています。

・出っ張りの場合
左上が光成分、右下が影成分。

・凹みの場合
左上が影成分、右下が光成分。

SVG要素にはbox-shadowは適用できません。
扨(さて)どうしたものか。色々と実験したのですが・・

これ⬆︎でどうでしょう。
正面のオブジェクトの後ろに、対角線方向のグラデーションを置いてやるとうまくいきそうです。

画像作成。


先づはイラレやVectornatorなどのソフトを使って、グレースケール(モノクロ)で原型を作ってみます。

プレビューしやすいよう、一時的に背景としての長方形を置きます。
完全な白(#fff)だと、それ以上明るい色を表現できないため、ほんのりグレー(#eee)にしました。

角丸の正方形でやってみます。

直線グラデーションを斜めに指定。

stop(色の変わり目)は「背景色に対して明るい色」「背景色と同色」「背景色より暗い色」の3点を置いています。
配色についての細かな調整は後からコードで行うので、あまり気にしなくても構いません。

前面に1周り小さい角丸正方形を置き、塗りを背景色と同じにします。
それっぽくなってきましたね。

両方の角丸正方形に、ぼかし効果をかけておきました。
これについてもコードで調整可能ですが、とりあへずベクターソフト上で施しておきます。そのほうが後のコーディングが楽に成増。

ちなみに凹ませたい場合には、背面にあるグラデーションの向きを180°回転させることで表現できます。
この「正面」と「グラデーション」の1セットがあれば、凹凸の両方に使いまわすこともできます。

周りと調和した配色。


作った画像をSVGとして書き出します。
ベクターソフトから書き出したままの状態では見づらいので、少し整理しました⬇︎。

<svg viewBox="0 0 841.9 595.3"> 「「3」」 <filter id=「「5"bokasi"」」> <feGaussianBlur stdDeviation="4"></feGaussianBlur> </filter> 「「3」」 <linearGradient id=「「5"grad"」」 gradientUnits="userSpaceOnUse" x1="236.934" y1="113.6269" x2="604.9558" y2="481.6487"> bb「「3」」 bb<stop offset="0.1857" style="stop-color:#FFFFFF"/> bb<stop offset="0.4787" style="stop-color:#EEEEEE"/> bb<stop offset="0.7752" style="stop-color:#B5B5B6"/> </linearGradient> 「「3」」 「「3」」 <path id = 「「5"grad_rect"」」 d="M584.5,490.1h-327c-16,0-29-13-29-29v-327c0-16,13-29,29-29h327c16,0,29,13,29,29v327 C613.4,477.2,600.5,490.1,584.5,490.1z"/> 「「3」」 <path id=「「5"front_rect"」」 d="M555.3,461H286.6c-16,0-29-13-29-29V163.3c0-16,13-29,29-29h268.7c16,0,29,13,29,29V432 C584.3,448,571.3,461,555.3,461z"/> </svg>

各オブジェクト及びぼかし、グラデーション定義には個別のid名を付けておきます。
またプレビュー用に背景に置いていた長方形はコメントアウトし、非表示にしました。

■ CSS

<style type="text/css"> 「「3/* 正面の角丸正方形 */」」 #front_rect { fill:#eee; } 「「3/* 背面の角丸正方形 */」」 #grad_rect { fill:url(#grad); } 「「3/* 2つの角丸正方形 */」」 #front_rect,#grad_rect{ filter:url(#bokasi); } </style>

グラデーションを含めた塗りと、ぼかし効果の指定はCSSに置きました。

それでは、ニューモーフィズム要素を配置する場所の背景色と馴染ませていきます

svg画像を配置する背景の色がこのような茶色系だったとします。

先づは、背景色のRGB値を求めます。
background-colorを指定している要素(ここでは#areaとします)を取得し、getComputedStyle( )で調べます。

■ JavaScript

const area = document.getElementById("area"); let areastyle = window.getComputedStyle(area); console.log(areastyle.backgroundColor); bb「「1// >>rgb(222,184,135)」」

出力した値rgb(222,184,135)をhsl値に変換します。hslを使うと、配色がとても楽に行うことができます。
RGB→HSL変換には、前回⬇︎の記事で使った関数を使いました。

HSL変換を使った配色や色指定。

2021.09.24
配色パターンを秒作。


■ JavaScript

「「3//RGB → HSL変換関数」」 to_hsl(222,184,135); bb「「1// >> 38 58 70」」

hsl値(色相:38,彩度:58%,輝度:70%)が得られました。
正面の角丸正方形の塗りに適用しましょう。

■ CSS

#front_rect{ fill:「「1hsl(33.8,57.6%,70%)」」; }

正面の色が背景と同じになりました。

次はグラデーションのstop(色勾配の分岐点)を配色します。

「「3」」 <「「4linearGradient」」 id= "grad" gradientUnits="userSpaceOnUse" x1="236.934" y1="113.6269" x2="604.9558" y2="481.6487"> bb「「3」」 bb<「「1stop」」 offset="0.1857" style="stop-color:#FFFFFF"/> bb<「「1stop」」 offset="0.4787" style="stop-color:#EEEEEE"/> bb<「「1stop」」 offset="0.7752" style="stop-color:#B5B5B6"/> <「「4/linearGradient」」>

先ほどのSVGコードのうち、⬆︎がグラデーションを定義している部分です。<linearGradient> 〜 </linearGradient>の中に、<stop>タグが3つあります。この<stop>タグが分岐点の内容を指定しています。

<stop offset = "0.1857" style = "「「1stop-color:#EEEEEE」」"/>

よくみると、CSS属性としてstop-colorという属性が指定されていますね。ここで分岐点の色が決められているのです。

3つの分岐点を、背景色のhsl値を使って指定しましょう。1つ目の分岐点は背景より明るめ、2つ目は背景色と同じ、3つ目は背景より暗め、で指定します。

明るさの指定はhslなら秒殺です。輝度の値を+-10%ずつずらしました。

<stop offset="0.1857" style="stop-color:「「1hsl(33.8,57.6%,「「580%」」)」」"/> <stop offset="0.4787" style="stop-color:「「1hsl(33.8,57.6%,70%)」」"/> <stop offset="0.7752" style="stop-color:「「1hsl(33.8,57.6%,「「560%」」)」」"/>

背景に調和したニューモフィズムができました。

ぼかしがやや深いので、もう少し薄めにしましょう。
ぼかしの大きさはfeGaussianBlurのstdDeviation属性で調整します。

「「3」」 <filter id= "bokasi"> bb「「3」」 bb<feGaussianBlur 「「1stdDeviation="2"」」> bb</feGaussianBlur> </filter>

もともとは「4」だったものを「2」まで落としました。

すこしシャープにすることができました。
お好みで調整しましょう。

凹みver。


凹みverを作るには、凸verを少し操作するだけで簡単に実装できます。
コード上でグラデーションの角丸正方形を複製し、前面に貼り付けます。またグラデーション定義も複製。それぞれid名を「grad_rect2」「grad2」としました。

「「3」」 <path id = 「「5"grad_rect2"」」 d="..."/> 「「3」」 <linearGradient id=「「5"grad2"」」 gradientUnits="userSpaceOnUse" 「「1x1="236.934" y1="113.6269" x2="604.9558" y2="481.6487"」」> bb「「3」」 bb<stop offset="0.1857" style="stop-color:#FFFFFF"/> bb<stop offset="0.4787" style="stop-color:#EEEEEE"/> bb<stop offset="0.7752" style="stop-color:#B5B5B6"/> </linearGradient>

linearGradientの開始タグ内にあるx1やy1属性は、グラデーション軸の始点と終点座標を指定しているものです。

複製した定義のグラデーション軸において、始点座標と終点座標を逆転させてやりましょう。

<linearGradient id= "grad2" gradientUnits="userSpaceOnUse" 「「1x2="236.934" y2="113.6269" x1="604.9558" y1="481.6487"」」>

その上でCSSで呼び出します。

■ CSS

#grad_rect,#front_rect,「「5#grad_rect2」」 { filter:url(#bokasi); } 「「5#grad_rect2」」 { 「「1fill:url(#grad2);」」 }

凹みバージョンができました。

ニューモフィズムをアニメーション。


扨(さて)いよいよアニメーションさせていきましょう。
このニューモフィズムデザインを「UIボタン」として使うケースを想定して、クリックすると凸凹が切り替わる、というものをやってみます。

仕組み。
SVG領域内に「正面の角丸正方形」→「凸のグラデーション」→「凹のグラデーション」の順に重ねて配置しておきます。
凹グラデーションは凸グラデーションの背面に回り込んでいるため、現在の見た目は凸状態です。

ユーザがクリックすると、前面にある凸グラデーションが縮小されて正面オブジェクトの後ろに隠れてしまう。その結果、背面の凹グラデーションが可視化されて、凸凹逆の状態になる、というものです。

動きを表現するだけならCSSの擬似クラス「:active」を使えば事足ります。
しかし実用性を考えたとき、on/offを認識して何らかの処理ができるようにしたい。そこで今回はWeb Animations APIを使って実装します。

■ HTML内SVG

「「1<g onclick = "onoff()">」」 「「3」」 <path id = "grad_rect2" d=.../> 「「3」」 <path id = "grad_rect" d=.../> 「「3」」 <path id= "front_rect" d=.../> 「「1</g>」」

はじめにオブジェクトの配置を整えます。
SVG内において、「正面の角丸正方形」→「凸のグラデーション」→「凹のグラデーション」の順に要素を重ねておきましょう。
3つを<g>で囲んでグループ化。グループのonclick属性として、このあと定義する「onoff( )」関数を指定しておきます。

■ CSS

#grad_rect { transform-origin:「「1center」」; }

CSSでも下準備。
3つの要素のtransform-origin(変形の基準)を「center」にしておきましょう。

ここで凸凹とon/offの関係を整理しておきます。

 ・凸がoff。初期状態です。このあと宣言するflag変数を「0」とします。
 ・凹がon。このときにflag変数「1」ということで。


それではJavaScriptを書いていきます。

■ JavaScript

「「3//on/offを判別するフラグ。off(初期状態)のときは0。」」 let flag = 0; 「「3//前面のグラデーションを取得」」 const grad_rect = document.getElementById("grad_rect"); 「「3//キーフレーム」」 let keyframes = [ bb{transform:"scale(1)"}, bb{transform:"scale(0.8)"} bb]; 「「3//2つのタイミング関数」」 「「3//① off→onの時は順方向に再生」」 let to_on = { bbduration:500, bbiterations:"1", bb「「4fill:"forwards"」」, bb「「1direction:"normal"」」 bb} 「「3//② on→offの時は逆方向に再生」」 let to_off = { bbduration:500, bbiterations:"1", bb「「4fill:"forwards"」」, bb「「1direction:"reverse"」」 bb}; 「「3//on/offを判別するflagの状態により、条件分岐」」 function onoff() { 「「3//フラグが0、つまりoff状態なら」」 if (flag == 0) { bbgrad_rect.animate(keyframes,「「1to_on」」); bbflag = 1; 「「3//フラグが1、つまりon状態なら」」 bb} else { bbgrad_rect.animate(keyframes,「「1to_off」」); bbflag = 0; bb} }

再生方向の違う2種類のタイミング関数を用意しました。flag変数の状態によって条件分岐しています。
またアニメーション終了時の状態を保つために、fillを「forwards」に指定しています。

完成。



⬆︎クリックすると凹凸が入れ替わります。

これで完成。お疲れ様でした!
状態変化とともにfrontの色を少し暗くしてみたり、小さくしたりして遠近感を出すのもいいかもしれませんね。いろいろ試してみてください。

長くなりました💧


最後までお読みくださり、ありがとうございました。
SVGを使ったニューモフィズムアニメーション実装にはいくつか手順をふむ必要がありました。

① 白黒で原型を作成

② web上の背景色と調和させる

③ WAAPIを使ってアニメーション

CSSを使った実装に比べると作業量が多くなってしまいますが、ここまで作り込んでおくと「UI部品」として幅広く機能させることができます。1つ作ればSVGの性質を利用して、複製・アレンジも自由に行うことが可能に。ぜひチャレンジしてみてください。

記事自体もとても長くなってしまいすいません。次回からはもっと簡潔なコンテンツを心掛けます(←ウソ)
ではまた〜 ♫



SVGでWeb Animations API。

2020.11.12
〽️ ネイティブJavaScriptでのアニメーション。

SVG、金属文字を表現。

2021.09.17
CGビギナーの課題曲。


SVGでボタンアニメーション【Web Animations API】。

2020.12.19
event.targetからオブジェクトを動かす。











「ふ」です。

swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。