SVG、use要素を使ったモーションパス。

〽️use要素の使い方。 〽️画像を準備。 〽️アニメーション実装 〽️マイナスの「遅れ」。 〽️いろんな要素でやってみよう。





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

こんにちは、「ふ」です。
SVGのモーションパス3回目、「大蛇編」。

タイトル部分のアニメーション、上に表示している1つの画像要素を順次複製して動かしています。

今回はSVGの<use>要素の使い方と、それを使って画像要素を複製しながらパスに沿って動かす方法を紹介したいと思います。

use要素の使い方。




<use xlink:href = " "/>

SVGの<use>要素は、1つの画像要素を使い回して描画することできる便利なものです。コードの記述量も削減でき、視認性もよくなります。



正方形をひとつ書きました。コードは下のようになっています(styleの記述は省略しています)。

<rect width="200" height="200"/>

これを<use>要素を使って使い回してみましょう。
まづこの正方形を参照できるよう、id属性を付けておきます。

<rect 「「1id = "base"」」 width="200" height="200"/>

<use>要素を記述し、参照させます。

<use xlink:href = 「「1"#base"」」/>

只今の結果。何も変わっていないように見えますが、元の正方形の上に同じものが重なっています。
複製したものをx方向に移動させてみましょう。

<use xlink:href = "#base" 「「1x = "300"」」/>

やはり重なっていました。「使い回し」は成功しています。

画像を準備。


では実際にuse要素で複製したものをアニメーションさせてみます。 タイトル部分にあった、「大蛇」を作っていきましょう。
まづは画像から作成していきます。今回もイラレを使用しました。

作成過程においてはSVGで出力した時に認識しやすいように、部品には名前を付けていきましょう。

元となる大蛇の胴体。こいつはアニメーションさせません。
idは「body」としました。

斑点を1つ作ります。idは「spot」。
いつものようにアートボードの左上、座標(0,0)に配置します。

はじめに作った胴体をベースに、要素の軌道となるターゲットパスを2本作ります。
パスの端点は斑点のサイズ分、アートボードからはみ出させておきます。viewboxの外側からアニメーション要素が入ってくるように見せるためです。

元にした胴体オブジェクトはクローズドパスでした。
そこから複製・切り取った2本のパスなので、パスの方向が互いに逆を向いているケースも考えられます。

パスの先端形状を施して方向を確認します。
逆になっている場合は、オブジェクト▶︎パス▶︎パスの方向反転を使って揃えておきましょう。

モーションパスのための画像の作り方については、前回前々回の記事⬇︎で詳しく説明しています。よろしかったら参考にしてください。

SVGでモーションパス(基本編)。

2020.08.18
〽️ 好きな軌道で画像を動かす。


SVG、モーションパスで複数の要素を動かす。

2020.08.29
〽️ 小技を集結させて実装します。

最後にもう1つ。アニメーションする斑点を胴体の形で切り抜くための、クリップパスを作成します。
胴体オブジェクトをそのままコピペ、リネームで構いません。

〜これで画像の準備は完了です。

アニメーション実装。


作成した画像をSVGで書き出します。

<svg version="1.1" ‥ > <path id=「「1"body"」」 ‥ /> <path id=「「1"clip"」」 ‥ /> <g id=「「1"spot"」」> <g>     <path class="st1" ‥ />          「「3〜略〜」」          <path class="st2" ‥ />     <path class="st3" ‥ />     <path class="st4" ‥ /> </g> </g> <path id=「「1"target1"」」 class="st5" ‥ /> <path id=「「1"target2"」」 class="st6" ‥ /> </svg>

斑点(spot)の部分は複数のオブジェクトで構成されているので、グループ化されていますね。
アニメーションを仕込む前に、クリップパスとターゲットパスの部分に手を加えておきます。




画像作成時には見やすいよう色を付けていたターゲットパスですが、非表示にしておきましょう。
SVGコード内の<style> 〜 </style>に、不透明度を0に指定する記述を追加します。




「「3< path id="clip" ‥ />」」 ⬇︎ 「「1< clipPath id="clip">」」 < path ‥ /> 「「1< /clipPath>」」

切り抜き用のオブジェクトはただの「path」として書き出されています。このままではクリップ用のパスとして参照できないので、修正を加えます。
外側を<clipPath>〜</clipPath>タグで囲み、<path>タグに指定していたid属性を削除。<clipPath>タグの方に移し変えておきます。

それでは斑点をアニメーションさせてみましょう。



「「1」」

<animatemotion>要素に指定する属性を、

・持続時間(dur):10s
・繰り返し(repeatcount):永遠
・角度(rotate):パスの角度に合わせる

としました。

そしてタグ内に<mpath>要素を記述し、作成した2本のターゲットパスのうち、上にあったものを参照させています。

「「4<g id = "spot_default" >」」 <g id="spot">     「「3〜略〜」」 </g> 「「1 」」 「「4</g>」」

ここで注意したいのが、どこに<animatemotion>要素を記述するかということです。
斑点(spot)タグの内部に記述すると、後から使い回してタイミングをずらしたアニメーションを指定した時に、2重にアニメーションが掛かってしまうことに成増。それはそれで興味深いのですが。

それを回避するために、<spot>要素の外側に<animatemotion>要素を記述します。
さらにそのままでは両者は関連付けがされていないので、<g>タグで囲んでグループ化させましょう。id名を「spot_default」としておきました。

結果を見てみます。

ひとまずうまくいってるみたいですね。
下のターゲットパスに対してもモーションパスさせてみます。ここでようやく<use>要素の出番です。

<g id = "spot_default" > 「「3〜略〜」」 </g> 「「1」」 <mpath xlink:href = 「「5"#target2"」」></mpath> 「「1」」

<use>要素は今作った「spot_default」グループの外側に記述して、「spot」要素だけを拾ってきます。
これでアニメーションが2重に掛かってしまうことは回避できます。

今度はモーションパスのターゲットには下のパス(target2)を参照させました。

複製してアニメーションさせることができました。
ここにアニメーション開始のタイミングを遅らせた「斑点」を追加していきます。

ただしあと1つ、問題が。

マイナスの「遅れ」。


これから「begin」属性を使ってタイムラグをつけた「斑点」を追加していくのですが、「begin」要素はあくまで「開始の遅れ」を指定するものです。

<animateMotion dur = "10s" repeatCount = "indefinite" rotate = "auto" 「「1begin = "〇〇"」」 > </animatemotion>

そうすると、アニメーションは大蛇の胴体に「模様がない状態」から始まってしまうことに成増。
どうすれば・・



マイナスの「遅れ」。


実験の結果、面白いことがわかりました。
begin属性には、「-」の値を指定することもできるのです。試しに「-5秒の遅れ」を指定してみましょう。

<animateMotion dur = "10s" repeatCount = "indefinite" rotate = "auto" 「「1begin = "-5.0s"」」 > </animatemotion>

「遅れ」を-5秒に指定すると、アニメーション開始時はこのような状態と成増。「−5秒遅れる」ということは、結果的に「+5秒後の状態から始まる」ということですね。

この「-の遅れ」を段階的に指定していけば、大蛇の胴体に模様がついている状態からアニメーションをスタートさせることができそうです。


<g id = "spot_default" > <g id="spot">     「「3〜略〜」」 </g> <animateMotion dur = "10s" repeatCount = "indefinite" rotate = "auto" 「「1begin = "-2.5s"」」> <mpath xlink:href = 「「5"#target1"」」></mpath> </animateMotion> </g> <animateMotion dur = "10s" repeatCount = "indefinite" rotate = "auto" 「「1begin = "-2.5s"」」> <mpath xlink:href = 「「5"#target2"」」></mpath> </animateMotion> <animateMotion dur = "10s" repeatCount = "indefinite" rotate = "auto" 「「1begin = "-4.5s"」」> <mpath xlink:href = 「「5"#target1"」」></mpath> </animateMotion> ・・・・・・・・・・・

デフォルトの斑点も、アニメーション開始時はviewboxの外にあるので「-2.5s」の遅れを指定しました。
下のパスに沿わせる1つ目の斑点も同じく「-2.5s」。

その後、上下のパスに沿わせる2つ目の斑点ペアは「−4.5s」。
3つ目のペアは「-6.5s」。

「-の遅れ」を2秒ごとに累積した値を順次指定していき、最終的には「-2.5s」「−4.5s」「-6.5s」「-8.5s」「−10.5s」の5つの斑点ペアを記述しました。

結果を見てみます。

良好です。当ページを再読み込みしても、ちゃんと「模様のある状態」からアニメーションがスタートします。試してみてください。




「「1<g id = "spot_group">」」 <g id = "spot_default" > 「「3〜略〜」」 </g> 「「3〜略〜」」 ・・・・・・・・・・・ 「「1</g>」」

いよいよ最後の仕上げです。
全ての斑点要素をグループ化。id名は「spot_group」としておきます。



これを胴体の形でクリッピングマスクしましょう。

これでついに完成です!
お疲れ様でした。

いろんな要素でやってみよう。


最後までお読みいただき、ありがとうございました。
前回の記事では実際にviewbox内に複数の要素を描画していたため、アニメーション待機中の要素が左上に見えてしまう、という問題がありました。しかし今回は2つ目以降のアニメーション要素をuse要素でその都度使い回しているので、そのような問題は起こりません。

今回は大蛇が通り過ぎるという、おどろおどろしいものを作ってみましたが、アニメーション要素だけ差し替えれば、色々な雰囲気のモーションパスを作ることができます。

これは大小2つの円を元となる要素とし、<use>要素を使って上下のパスにランダムに沿わせました。
大蛇の胴体は非表示、クリップパスはキャンセルさせてあります。一転して爽やかになりました。

皆さんも今回作ったモーションパスをベースに、楽しいアニメーションを作ってみてくださいね ♫ ではまた〜



関連記事

SVGアニメーション、エンドレスに流れる画像。

2020.07.23
〽️ タイトル部分に使えそう?ふふふ。


SVGアニメーション06、アニメーションに合わせてテキストの色を反転。

2020.07.15
〽️ 3つの長方形を動かします。











「ふ」です。

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