SVGで扇子のアニメーション。

〽️ ただの扇型」ではない。 〽️原型を準備。 〽️折りたたみアニメーション。 〽️開いた状態を作る。 〽️全体をアニメーション。 〽️次は柄をつけたい。





ただの「扇型」ではない。


こんにちは、「ふ」です。
今回はSVGで「扇子」を作ってアニメーションさせたいと思います。

単にオブジェクトを円弧上に広げていくだけなら、簡単なのですが........ 広がっていく中で「折りたたみ」感を表現するのに、工夫が必要でした。

おめでたいときや、冬休み(←執筆当時)の工作にどうぞ。

原型を準備。


Vectornatorやイラレを使って、原型となるイラストを作成しましょう。
「扇型」の描き方についてはいろんな方法が考えられるのですが、どのベクターソフトでも共通で操作できるものを紹介します。

円を描き、垂直な中心線を引きましょう。
中心線は円の端から端まで。はみ出さないようにしてください。
はみ出したり長さが足りなかったりすると、このあと中心から回転させたときにズレてしまいます。

中心線を2つ複製し、それぞれ+ー方向に15°ずつ回転させます。

同心円を追加します。
この円は扇子の「骨」と「紙?」の部分の境界線になるので、完成品をイメージして大きさを調整してください。

紙?の部分は「扇面」と呼ぶらしいです(←調べた)。

扇面の「山」と「谷」の1セットを、ペンツールなどを使って⬆︎のように描きます。長方形を描いて変形させても良いかと思います。

円弧の部分は直線で結びました。そのほうが「折りたたみ感」が出ます。

骨を1つと、回転軸(←「要『かなめ』」と言うらしいです)を描きました。
要の円は、始めに描いた円と中心を一致させてください。アニメーションさせるときの基準点として使用します。

全体の大きさを調整します。
扇子は150°まで開くので、1番外側の円の直径がアートボード(のちの可視範囲)に収まるくらいがいいでしょう。

「扇子面の1セット」「骨」「要」の3つを残し、他のオブジェクトは作画時の補助として使用したものなので、削除します。

色をつけました。
「扇子面の1セット」には明暗をつけておくと、それらしくなります。また「骨」のオブジェクトは最背面にしておきましょう。

これで原型は完成です。
SVG形式で書き出し、あとはコーディングで編集していきましょう。

折りたたみアニメーション。


作成した「骨と扇面の1セット」を使って、折りたたみアニメーションを作ってみましょう。
原型のSVGデータを、HTMLに流し込みます。

<svg viewBox="0 0 841.9 595.3" > <style type="text/css"> .st0 {fill:#FFFFFF;stroke:#999;stroke-width:0.25;} .st1 {fill:#EEEEEE;} .st2 {fill:#FECE5C;} </style> 「「3<!--骨-->」」 <path class="st2 「「1kaname」」" d="M426.9,553.5h-14.7c-4.1,0-7.5-3.4-7.5-7.5V52.9c0-4.1,3.4-7.5,7.5-7.5h14.7c4.1,0,7.5,3.4,7.5,7.5V546 C434.4,550.2,431,553.5,426.9,553.5z"/> 「「3<!--扇面:表(白)-->」」 <polygon class="st0 「「1kaname」」" points="419.5,46.8 542.3,63 464,355 419.5,349.7 "/> 「「3<!--扇面:裏(グレー)-->」」 <polygon class="st1 「「1kaname」」" points="296.8,63 419.5,46.8 419.5,349.7 375.1,355 "/> 「「3<!--要-->」」 <circle cx="419.5" cy="521" r="11.2"/> </svg>

「要」の円の中心は、全てのオブジェクトのtransform-origin(変形の基準)となります。
各要素にいちいちtransform-originプロパティを指定するのも面倒なので、class名をつけて一括でできるようにしましょう。class名は「kaname」としました。

originをpxで(裏技)。



<circle cx=「「5"419.5"」」 cy=「「5"521"」」 r="11.2"/>

⬆︎要の円オブジェクトのコードです。このcxとcyの座標が回転軸と成増。
本来であれば、viewBoxの " 0 0 841.9 595.3 " をもとに割合を計算→%値にしてtransform-originに指定するのですが、ちょっとした発見がありました。

.kaname { transform-origin:「「5"419.5"」」px 「「5"521"」」px; }

というように単位「px」を付けて指定すると、そのままSVGにおける座標値として扱われます。
扇子の各部品の基準指定はこれでOKです。


これは正規の方法とは言えないので、後の仕様変更により使えなくなる可能性もあります。
そのときは素直にviewBox値から算出するようにしましょう。

折りたたみを表現。

現在の状態⬆︎です。
扇面のオブジェクト2つには、さらにclass名を追加します。「ougi」としました。

「「3<!--扇面:表-->」」 <polygon class="st0 kaname 「「1ougi」」" points="419.5,46.8 542.3,63 464,355 419.5,349.7 "/> 「「3<!--扇面:裏-->」」 <polygon class="st1 kaname 「「1ougi」」" points="296.8,63 419.5,46.8 419.5,349.7 375.1,355 "/>

扨(さて)、折りたたみ表現。
rotateY(y軸に対しての回転)やskewY(傾斜)など色々試したのですが、最終的にはscaleX(水平方向の拡大/縮小)を採用しました。

.ougi { animation:ougi 4s linear alternate infinite; } @keyframes ougi { from { transform:「「1scaleX(0)」」; } }

キーフレームは「from」の状態だけ指定すればOKです。

2つのオブジェクトはy軸対称になっているので、折りたたみ感が表現できます。

開いた状態を作る。


扇面の1セットができたところで、これを左右に2つずつ、複製して追加しましょう。

SVGの要素は先に記述したものが背面に重なります。扇子が順番どおりに開閉するよう、「マスターの1セット」の前面に2つ、背面に2つ記述します。

<g id = 「「1"copy2"」」 class = 「「5"kaname set"」」> <path class="st2 kaname" d="M426.9,553.5h-14.7c-4.1,0-7.5-3.4-7.5-7.5V52.9c0-4.1,3.4-7.5,7.5-7.5h14.7c4.1,0,7.5,3.4,7.5,7.5V546 C434.4,550.2,431,553.5,426.9,553.5z"/> <polygon class="st0 kaname ougi" points="419.5,46.8 542.3,63 464,355 419.5,349.7 "/> <polygon class="st1 kaname ougi" points="296.8,63 419.5,46.8 419.5,349.7 375.1,355 "/> </g> <g id = 「「1"copy1"」」 class = 「「5"kaname set"」」> <path class="st2 kaname" d="M426.9,553.5h-14.7c-4.1,0-7.5-3.4-7.5-7.5V52.9c0-4.1,3.4-7.5,7.5-7.5h14.7c4.1,0,7.5,3.4,7.5,7.5V546 C434.4,550.2,431,553.5,426.9,553.5z"/> <polygon class="st0 kaname ougi" points="419.5,46.8 542.3,63 464,355 419.5,349.7 "/> <polygon class="st1 kaname ougi" points="296.8,63 419.5,46.8 419.5,349.7 375.1,355 "/> </g> 「「3<!--master-->」」 <path class="st2 kaname" d="M426.9,553.5h-14.7c-4.1,0-7.5-3.4-7.5-7.5V52.9c0-4.1,3.4-7.5,7.5-7.5h14.7c4.1,0,7.5,3.4,7.5,7.5V546 C434.4,550.2,431,553.5,426.9,553.5z"/> <polygon class="st0 kaname ougi" points="419.5,46.8 542.3,63 464,355 419.5,349.7 "/> <polygon class="st1 kaname ougi" points="296.8,63 419.5,46.8 419.5,349.7 375.1,355 "/> <g id = 「「1"copy3"」」 class = 「「5"kaname set"」」> <path class="st2 kaname" d="M426.9,553.5h-14.7c-4.1,0-7.5-3.4-7.5-7.5V52.9c0-4.1,3.4-7.5,7.5-7.5h14.7c4.1,0,7.5,3.4,7.5,7.5V546 C434.4,550.2,431,553.5,426.9,553.5z"/> <polygon class="st0 kaname ougi" points="419.5,46.8 542.3,63 464,355 419.5,349.7 "/> <polygon class="st1 kaname ougi" points="296.8,63 419.5,46.8 419.5,349.7 375.1,355 "/> </g> <g id = 「「1"copy4"」」 class = 「「5"kaname set"」」> <path class="st2 kaname" d="M426.9,553.5h-14.7c-4.1,0-7.5-3.4-7.5-7.5V52.9c0-4.1,3.4-7.5,7.5-7.5h14.7c4.1,0,7.5,3.4,7.5,7.5V546 C434.4,550.2,431,553.5,426.9,553.5z"/> <polygon class="st0 kaname ougi" points="419.5,46.8 542.3,63 464,355 419.5,349.7 "/> <polygon class="st1 kaname ougi" points="296.8,63 419.5,46.8 419.5,349.7 375.1,355 "/> </g>

コピペしたセットは<g> 〜 </g>で囲んでそれぞれid名「copy1〜4」を付けています。
そしてこれらも「要」を基準に動かすので、class名「kaname」を指定しました。さらに、アニメーションのキーフレームを一括で指定できるよう、もひとつclass名「set」も付けておきます。

現在の状態(アニメーションは一旦OFFにしています)。まだ同じところに重ねられているので、見た目は変化ありません。

1セットあたり30°ずつ回転させましょう。

#copy2 { transform:rotate(「「1-60deg」」); } #copy1 { transform:rotate(「「1-30deg」」); } #copy3 { transform:rotate(「「130deg」」); } #copy4 { transform:rotate(「「160deg」」); }

大分それらしくなってきましたね ♫

あとは扇子の外側には、「親骨」というものが付いています。
骨のオブジェクトを2つ複製。1つは全ての最背面に、もう1つは最前面の「要」オブジェクトの1つ後ろに配置しましょう。

<path id = 「「1"oya_usiro"」」 class="st2 kaname 「「5set」」" d="M426.9,553.5h-14.7c-4.1,0-7.5-3.4-7.5-7.5V52.9c0-4.1,3.4-7.5,7.5-7.5h14.7c4.1,0,7.5,3.4,7.5,7.5V546 C434.4,550.2,431,553.5,426.9,553.5z"/>  「「3〜 masterとcopy1〜4のコード 〜」」 <path id = 「「1"oya_mae"」」 class="st2 kaname 「「5set」」" d="M426.9,553.5h-14.7c-4.1,0-7.5-3.4-7.5-7.5V52.9c0-4.1,3.4-7.5,7.5-7.5h14.7c4.1,0,7.5,3.4,7.5,7.5V546 C434.4,550.2,431,553.5,426.9,553.5z"/> 「「3<!--要-->」」 <circle cx="419.5" cy="521" r="11.2"/>

idを「oya_mae」「oya_usiro」とし、さらに先ほどアニメーション用に用意したclass名「set」も付与しておきます。

#oya_usiro { transform:rotate(-75deg); } #oya_mae { transform:rotate(75deg); }

親骨に角度を付けます。
扇面の1ピースの角度は15°なので、左右に.....75°ずつですね?

開いた状態が完成しました。

全体をアニメーション。


それでは全体をアニメーションさせましょう。

一時的にキャンセルさせていた「1セットのアニメーション」を復活させた状態です。

扇子全体を開閉させるアニメーションを実装します。

扇子の部品はすべて、「rotateさせて開いた状態」で作成してきました。したがって色んな角度に開いてはいるものの、「rotateの角度を0°に戻す」という1つのキーフレームにまとめることができます。
開閉させる部品にはclass名「set」を付与していたので、一括で指定します。

.set { animation:set 4s linear alternate infinite; } @keyframes set { from { transform:rotate(0deg); } }

これで完成です。お疲れ様でした!
好みの色などを付けて、楽しんでください。

次は柄をつけたい。


最後までお読みくださり、ありがとうございました。
今回の扇子のアニメーション。実物の動画を参考にしながら、2Dに落とし込めるようにアレンジしてみました。上手くできましたでしょうか?

今回は仕組みを紹介したかったので無地のオブジェクトを使って進めてきましたが、次はここに、自由な画像を貼り付けられるようにしたいと思います。ただいま作成中につき、完成次第記事をアップしたいと思います。お楽しみに。

ではまた〜 ♪



SVGアニメーション、 回転の中心を指定する。

2021.03.09
座標を取得して%変換。


CSSアニメーション、中間テスト。

2021.06.03
基本編を終えたらチャレンジしましょう。












「ふ」です。

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