〽️「キラ」が1つあるSVG。 〽️外側のSVGに配置。 〽️ランダムに発生させる。 〽️分布や大きさを工夫しよう。
⬆︎SVGついてのまとめページ、CSSアニメーションの基本コーナーはこちら。
こんにちは、「ふ」です。
ヘッダにあるように、「ランダムに発生するキラキラ」をSVGアニメーションで作っていきましょう。
今回は、「SVG in SVG」でいきたいと思います。
■ inner.svg
内側のSVG画像はこのようなもの。
1つの「キラ」がアニメーションしています。
■ outer.svg
外側のSVGも準備します。
みなさんはキラキラさせたい要素をこの中に配置してください。
JavaScriptを使い、内側のSVG画像を複製。時間差で外側のSVG領域にどんどん追加していきます。
このとき、乱数を使って位置や大きさを毎回変化させます。
尚、追加したままでは外側のSVG領域内に「キラ」が無限増殖してしまいます。
アニメーションの終了イベントを検知したら、その要素は削除するようにしましょう。
〜複雑そうですが、意外と短いコードで実装することができます。
いっしょに作っていきましょう🎵
先づは内側のSVGからです。
アニメーションさせる「キラ」を1つ埋め込みましょう。
ベクターソフトで、正方形を描きます。
その上に円を4つ重ねてグループ化(最初の正方形はグループに入れないでください)。
パスファインダーで切り抜き。
色や線をお好みで指定して、「キラ」が完成です。
ベクターソフトを使えば「秒」で作れますね。これをSVG形式で書き出しましょう。
■ HTML
書き出したコードをHTMLの <body> 〜 </body>内にインラインで貼り付けます。
id名をつけておきます。
SVGタグには「inner」、「キラ」のオブジェクトには「kira」としました。
「キラ」をアニメーションさせましょう。
0%から50%にかけて徐々に大きくなり、不透明度も上げていきます。50%以降は縮小・不透明度も下げていきます。
背景が明るい場合には「キラ」が目立たなくなるため、枠線もアニメーションさせました。これについてはお好みで構いません。
■ CSS
「キラ」のアニメーションができました。
現在は見やすいようにアニメーションの繰り返しは「infinite(無限)」にしています。
外側のSVGを準備します。ここでは、<body> 〜 </body> 内にSVG領域を設けて画像を挿入してもいいですし、好きなSVG画像のコードを直接流し込んでもかまいません。
■ outer.svg
「ふ」は最初に紹介した「outer.svg」のコードを流しこむことにしました。
■ HTML
参照できるようにid「outer」としています。
HTMLで画像を重ねる、便利な方法。
positionやz-index指定なし。
SVGに画像をぴったりと配置〜
preserveAspectRatio。
縦横比が違っても安心。
SVG領域に画像を配置する方法やサイズ調整については、これら⬆︎の記事にて詳しく紹介しています。
次に先ほど作成したinnerのコードを、outerのSVGタグ内に流し込んでしまいます。
SVGでは、自身の中に別のSVG領域を設けることが可能なんです。
■ HTML
現在のブラウザ表示です。outerのSVG領域内にinnerも追加されました。
・ 注意
illustratorでSVG画像を作成した場合、inner/outerの各要素のクラス名が重複してしまい、その結果CSSが汚染し合う可能性があります。
コードエディタでclass名が被らないように調整が必要です。
今innerのSVGはouterの領域に対して、座標でいうところの(0,0)に位置しています。
いずれ複製してランダムに配置したいのですが、この1つ目の「キラ」は定位置になってしまいます。常に表示されているとあまりよろしくないため、outer領域の外に逃がしてしまいましょう。
「逃す範囲」に関して。
このSVGアニメーション、端のほうに配置された「キラ」が切れてしまわないように、overflowを「visible」にしたい方もいるかと思います。
そうしたときにも表示されてしまわないよう、思い切ってHTML領域の外側まで飛ばしてしまいます。xを「-300%」にしました。
■ HTML
さらに「キラ」のアニメーション指定で、繰り返しは1回だけに直しましょう。←これを忘れると無限増殖します。
animation-iteration-countの初期値は「1」なので、最初に記述していた「infinite」を削除するだけで大丈夫です。
■ CSS
innerは高飛びさせたので見えなくなりました。
これでHTMLの記述は完了です。
それではJavaScriptを使ってinnerを複製し、outerの領域内にランダムに発生させます。
■ JavaScript
① innerとouterの要素を取得。
② cloneNodeメソッドでinnerを複製します。
このときの引数は、「子要素も含めて複製するか」の真偽値を指定します。もちろん内部の「kira」も一緒に複製するため、「true」としておいてください。
③ アニメーション終了後に要素を削除。
最後にsetIntervalで一定時間おきにouterに追加していくのですが、そのままでは無限に「キラ」が増殖してしまいます。
animationendイベントを利用し、終了時に要素を削除するイベントハンドラを仕込みましょう。
④ 位置と大きさをランダムに。
JavaScriptのMath.randomメソッドは、0〜1の乱数を返します。これをその時々のinnerのxy座標及びwidth採用します。
0〜1の返り値を0〜100%に振り分けたいので、100倍にしてから文字列化し、setAttributeで属性に指定します。
大きさに関しては、width/height属性の両方に変数「ookisa」の返り値を指定します。元の「キラ」ではデカ過ぎるので、MAXで50%の大きさとしました。
⑤ outerに追加
appendChildで、複製したinnerをouterに追加しています。
A 一連の処理を関数化
複製→加工→追加までの処理を関数「random( ) 」としてまとめます。
B 一定時間おきに実行
setIntervalで、関数random( )を一定時間おきに実行させます。「ふ」は0.28秒としたのですが、間隔はお好みで調整してください。
ここまでの結果⬆︎です。
しばらく眺めているとわかるのですが、「キラ」の分布が全体的にouterのやや右下に分布してしまっています💧これはどういうことなのでしょうか?
いったんアニメーションは置いといて、静止した状態で考えてみましょう。
innerの大きさは0〜50%の範囲でランダム変化させています。中間値の「25%」としたとき。
SVGのx、y属性は、左上が基準と成増。
xyともに「0%」のときと、「100%」のときのinnerの配置はこの⬆︎ように。
つまりinnerの分布が、outer領域に対して右下に25%ずれてしまっている、ということです。
Math.randomの返り値を、半分の12.5%ずつ左上にずらしましょう。
■ JavaScript
これで結果をみてみます。
均一に分布するようになりました。
これで完成です。お疲れ様でした!
最後までお読みくださり、ありがとうございました。
今回はSVGの中にSVGをランダムに発生させる、というのをやってみました。うまくできましたでしょうか?
ちなみにMath.randomで返される値をいじると、なかなか楽しい効果が得られます。
例えば、「キラ」をある程度以上の大きさにまとめたい場合。
■ JavaScript
この⬆︎ように、innerの大きさが20〜50%の範囲で振り分けられます。
他にも「中央よりに分布させたい」など挑戦してみると楽しいかとおもいます。
また「キラキラ」以外にもこのランダム発生は使えそうですね。いろんな要素で試してみてください。
ではまた〜 🎵🎵🎵
SVGアニメーション、 回転の中心を指定する。
2021.03.09
座標を取得して%変換。
SVG アニメーション、カメラのシャッターを再現。
2021.04.11
「アニメーションごと」重ねていく。
ページめくりアニメーション 作り方。
2021.02.02
画像を読み込むだけで実装。
swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。