SVG アニメーション、パスの内側を切り抜いて透過させる。

〽️不透明度を移植する。 〽️実装してみましょう。 〽️マスクは外側に。 〽️もうちょっと遊ぼう。





⬆︎SVGついてのまとめページはこちら。

こんにちは、「ふ」です。
SVGの「clipPath」については、当サイトでも何度か取りあげてきました。「パスの内側だけを表示・外側を非表示にする」というものです。

それとは逆に、「パスの内側だけ画像をくり抜いて透過させる」にはどうすればいいのでしょうか? SVGにはイラレやVectornatorの「パスファインダー」に該当する便利なコマンドは用意されていません。

実装にはちょっとした工夫が必要です。
今回はその方法について紹介します。

不透明度を移植する。


くり抜きには<mask>要素を利用します。
SVGのマスク要素は、マスクを掛けられる側の要素に自身の「不透明度」を移植します。ここでいう不透明度は、rgbaの「a」や、CSSの「opacity」に該当するものではありません。

普段よく使っている「不透明度」とは別に、「色そのものが持つ不透明度」という指標があり、rgbaそれぞれの値から算出されます。

ピクセルの情報から算出される不透明度 「「1  (0.2125*r+0.7154*g+0.0721*b)*alpha 」」

rgbaの「a」を「1(完全な不透明)」で固定した場合。

完全な黒(#000)であれば不透明度0に、完全な白(#fff)であれば不透明度1と成増。
マスク要素は、この不透明度をマスクを掛けられる側に移植します。

「ふ」の画像にマスクを掛けて、確かめてみましょう。

黒いオブジェクトでマスクを掛けた場合、掛けられる側には「不透明度0」が移植され、完全な透明に成増。黒オブジェクト以外の領域には何もないのでこちらも不透明度0が移植され、結果的に何も表示されない状態に。

白いオブジェクトでマスクをすると、「不透明度1」が移植され、掛けられる側は完全な不透明に。
つまり、マスクされる側に何も影響を与えません。

それではこのような、白いオブジェクトの中に黒いオブジェクト。
これでマスクを掛けた場合、どうでしょうか?

黒オブジェクトの部分だけがくり抜かれて透過されました。

★この方法を使います★。
オブジェクト+白い長方形を準備して対象のオブジェクトにマスクを掛ければ、「くり抜いて透過」が実装できます♪



マスクと不透明度の関係については、こちら⬇︎の記事で詳しく紹介しています。

SVGアニメーション、mask要素で手書き風テキスト。

2020.10.01
〽️ <mask>要素について理解しましょう。


実装してみましょう。


では実際にコードを書いて試してみましょう。
このような画像⬆︎を準備しました。

オブジェクトの構成はこのようになっています。

・マスクとなる側(左)。
黒テキスト(アウトライン化済)と、白長方形をアートボード(表示領域)いっぱいに広げます。

・マスクされる側(右)は、
ワイン色の長方形が1つ。

〜「テキストの形」でワイン長方形をマスクします。

■ HTML


<body> <svg viewBox="0 0 792 612" ...> <style type="text/css">  .... </style> 「「1<mask id = "mask1"> ..②」」 「「3<!--白長方形-->」」 <rect class="st0" width="792" height="612"/> 「「3<!--テキスト-->」」 <path class=.../> <path class=.../> ..... 「「1</mask>」」 「「3<!--ワイン長方形-->」」 <rect 「「1id = "rect1" 」」y="37.2" class="st3" width="231.6" height="405.5"/> 「「1..①」」 </svg> </body>

画像をSVG形式で書き出し、HTMLの<body> 〜 </body>内にコードを埋め込みました。

① ワイン長方形にはid「rect1」をつけておきました。

② テキストと白長方形を<mask>タグで囲み、マスク用のオブジェクトとします。
こちらはid「mask1」としました。

現在の状態です。テキストと白長方形はマスクオブジェクトとしたため、表示されません。
ワインをCSSで参照して、マスクを指定します。

■ CSS


#rect1 { 「「1mask:url(#mask1);」」 }

結果はこのように。テキストの部分だけワイン長方形を非表示にすることができました。

マスクは外側に。


「逆クリップパス」が成功したところで、これをアニメーションさせていきましょう。
CSSアニメーションで、ワイン長方形を左から右へと動かします。

■ CSS


#rect1 { mask:url(#mask1); 「「1animation:rect1 2.5s linear infinite;」」 } @keyframes rect1 { 0% { 「「1transform:translateX(-20%)」」; } 100% { 「「1transform:translateX(110%)」」; } }

これでワインが右へと移動するにつれて、くり抜かれたテキストが終わりまで表示されるはず?
〜結果を見てみます。

おや?

最初のマスク状態で、ワイン長方形が動いてしまっています💧

原因は、ワイン長方形に直接マスクを掛けていたためです。
要素に直接マスクを掛けた時点で「その要素に内包されているプロパティ」になってしまっていたのです。
静止画像なら問題なかった。しかしこの要素に対してアニメーションを指定した場合、内包されているマスクごと動いてしまうのです。

対策。
画像要素を<g> 〜 </g>で囲んでグループ化し、そのグループに対してマスクを掛けることで解消します。
コードを書き直しましょう。

■ HTML


「「3<!--グループで囲む-->」」 「「1<g id = "rects">」」 bb「「3<!--ワイン長方形-->」」 bb<rect id = "rect1" y="37.2" class="st3" width="231.6" bbheight="405.5"/> 「「1</g>」」

■ CSS


#rect1 { 「「3/*カットする。 mask:url(#mask1); */」」  animation:rect1 2.5s linear infinite; } 「「1#rects { 「「3/*ここに指定し直す。*/」」 「「4mask:url(#mask1); 」」 }」」 @keyframes rect1 { ・・・・ }

結果は⬇︎のように。

うまくいきましたね♪ お疲れ様でした。

もうちょっと遊ぼう。


さらにid「rect2」として、長方形を追加してみます。
先程の「rects」グループ内に要素を追加すると自動でマスクが掛かります。

■ HTML


<g id = "rects">」」 bb<rect id = "rect1" y="37.2" class="st3" width="231.6" bbheight="405.5"/> bb「「1<rect id = "rect2" x="316.2" y="169.3" class="st2" bbwidth="231.6" height="405.5"/>」」 </g>

CSSで別のアニメーションをつけました。

■ CSS


#rect2 { 「「5mix-blend-mode: difference;」」 animation:rect2 2s linear alternate infinite; } @keyframes rect2 { 0% { transform:translateX(50%); } 100% { transform:translateX(-50%); } }

継続時間や方向も変えています。ついでにカラーブレンドも仕込みました。

こんな感じで、色々と遊んでみてください。フフフ。
マスク側のテキスト部分を動かしてみる、というのも面白そうですね。

最後までお読みいただき、ありがとうございました。
また面白いアニメイションが思いついたら紹介させていただきます。ではまた〜 🎵



SVGアニメーション、 回転スワイプで画像切り替え。

2021.02.27
ポイントは「2重クリップ」。

SVGアニメーション05、アニメーションしている部分をクリッピング(マスク)する。

2020.07.06
〽️ テキストの内部だけアニメーション。












「ふ」です。

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