ローディングのくるくる
上のアイコンはサンプルとして表示しているだけなので、待っていても何も起こりませんけれど、一眼でいかにも読み込み中だとわかるし、待たなきゃとさえ思わせてくるアイコンですよね;)。そんな、ローディング中を代表するくるくる動くアイコンの作り方のメモです。
仕組み
ローディングの動きは、いっぺんにやろうとするとこんがらがっちゃうので、「くるくる回る動き」と、「伸び縮みする動き」に分けて考えるとわかり良いです:)。
伸び縮みする動きを、円じゃなくて、直線に適用してみると下サンプルのようになっています。線の上にカーソルを乗せると(タップすると)仕組みが見えます。
線が伸び縮みしているように見えるけれど、実は伸びても縮んでもなくて、同じ長さの線が左から右へ通り過ぎてるだけなんですね:D。
作り方
くるくる動くアイコンは、SVGとCSSを使って作ります。
SVGは円を描画するため。CSSは円の回転と、線を動かすために使います。
図形を用意
まずは土台となる図形を、SVGで用意します。と言っても正円なので、イラレを起動するまでもなく、がんばって覚えれば自力で描けちゃえます;D。 htmlファイルに直接、下ソースコードのように記述します。
SVGを100px×100pxの正方形として表示して、その中央に半径40pxの正円を描く、ということになります:)。
svg要素で、SVGの表示サイズと表示範囲(※詳しくは後述)を指定。circle要素は、cx
とcy
が円の中心点、r
が円の半径を表しています。まだ真っ黒な玉ですけれど、ローディングらしい見た目になるように、CSSを追加します。
見た目をぽくする
さっきの真っ黒の玉に、塗り色はなし、線の色は青く、線の太さはちょっと太めの10px※になるように、CSSで以下のように指定します。
値に単位を付けなければpx
として適用されます。ただし、svg要素のサイズに対して相対的な太さなので注意。
輪郭線を分割する
SVGの線を分割するのには、stroke-dasharrayプロパティを使います。
stroke-dasharray
- 線を破線にするためのプロパティ。
指定した値を交互に、線・隙間・線・隙間…という具合に適用する。例えば、stroke-dasharray: 10, 20, 30
と指定すると、10px(線)・20px(隙間)・30px(線)・10px(隙間)…、という具合の破線になる。値がひとつの場合は、線と隙間の間隔が一定な破線になる。
このプロパティを、さっきの正円に適用すると下サンプルみたくなります。
破線の長さを、円周よりもちょっと短いくらいにすれば、ローディングぽい見た目になるってわけ:)!
円周の長さは「直径×円周率(π)」なので、80 * 3.14
ということ。ここでは、円周の長さよりも20px短めの破線になるように、calc()関数を使って、下記のように指定することにします。
うん、ローディングぽい、いまにも廻り出しそうです;D! いよいよ、これを動かしてゆきます!
CSSのcalc()関数について、詳しくは下記ページを参照のこと。
動かし方
ローディングの「くるくる回る動き」と「伸び縮みする動き」を順番につくってゆきます。
まずは「伸び縮みする動き」から:)。
伸び縮みする動き
「伸び縮み」とはいえ、実は、同じ長さの線が、表示範囲を通り過ぎれば、伸び縮みしているように見えるのでした。
SVGの線を動かすのには、stroke-dashoffsetプロパティを利用します。
stroke-dashoffset
- 線の始点を指定するためのプロパティ。
stroke-dashoffset: 10
と指定すると、始点が10px手前(左方向)に移動する。stroke-dashoffset: -10
とすると、始点が10px先(右方向)へ移動する。 -
上サンプルでは、svg要素のサイズが分かるよう、破線の背景にもう一本、細い線を表示させてます。
線の始点の位置を徐々に変化させていけば、破線が動いているように見えるはずです。
下サンプルでは、stroke-dasharray: 20
の破線に対して、stroke-dashoffsetプロパティの値を10pxずつ右方向へ動かしています。
始点が、破線の線と隙間の長さ分移動した時に、ちょうど元の位置に戻ってます。つまり、stroke-dasharray
の値の2倍移動するのを繰り返せば、破線が動き続けているように見えますね:D!
線の始点の変化を@keyframes規則で定義したらば、そのキーフレームをanimationプロパティを使って、svg要素に適用します。
下サンプルでは、「線の位置を、0
から右方向へ40px
移動させる」という、loader
と名付けたアニメーションを、2秒(2s
)かけて、無限(infinite
)に繰り返すように指定しています。
Safariで変
と思いきや、Safariで見てみると、なんだか動きが変ですね…。ひとつ前のサンプルも、他のブラウザと違う感じになってます(下図):(。
どうやらSafariでは、stroke-dashoffsetプロパティを負の値で指定すると、stroke-dasharrayプロパティで指定した値1ループ分で折り返しちゃうみたいなんです…X(。
下のサンプルでは、stroke-dasharray: 20 20 10
と指定した破線の始点を、10pxずつ右方向へ動かしています。
Safariで見ると下図みたく、stroke-dasharray
1ループ分(50px)ズレたところで、始点が出戻っちゃってるわけですねー。-60px
となった時、-10px
と同じ状態に戻ります。
なので、Safariのために、stroke-dasharray
の値は必ず、線と隙間ワンセットにする必要があります。
よし、これで大丈夫;D!
あとは、破線の長さをsvg要素の幅よりちょい短めにして、アニメーションすれば、下サンプルのような感じ。冒頭の「伸び縮みする動き」と同じ感じのができました!
ここでは、svg要素の幅250pxよりも20px短い230pxの破線にしています。
正円に適用
前述までの「伸び縮みする動き」の破線を、正円にも、円周よりちょい短めで適用します。80 * 3.14
が、251.2
で割り切れるので、もうcalc()関数は使わずに、ちゃんと計算した値でもって指定することにします。251.2 - 20 = 231.2
ですけど、キリよく230
で指定:)。
あとはこれを回せば出来上がり。新たに「くるくる回る動き」を@keyframes規則を定義して、さっきのanimation
の値のあとに、カンマ区切りで書き足します。
うん?なんか思ったのと違いますね…:‹。
回転が途中で止まるし、回転がゆっくりの時にいちばん短くなって欲しいのに、短い時がものすごく一瞬。伸び縮みするタイミングが悪いみたいです…X(。
くるくる回る動きは、回転スピードが一定になるようにlinear
を追記して、伸び縮みするタイミングは、破線の始点を半分手前(左方向)にズラしてみます。
うん、だいぶいい感じ! けどもうちょっとニュアンスを気持ちよくしたいなぁ…:ω
微調整
くるくる回るスピードと、伸び縮みするスピードが同じだと単調なので、ちょっとだけズラしてみます。アニメーションの速さだけ変えるときは、animation-durationプロパティを使います。animationプロパティの値がふたつあるので、animation-duration
の値もふたつずつ、カンマ区切りで指定します。ひとつめの値がloader
(伸び縮みアニメ)の速さ、ふたつめの値がloading
(くるくる回るアニメ)の速さになります。
ここでは試しに2パターン用意。
ふたつめの、伸び縮みのスピードよりも回るスピードが速い方がいいかなー:‹。あともうちょっとだけ伸び縮みのスピードを速めて、1.4s, 1.2s
にすることにします。
伸び縮みの動き具合もいろいろ試してみます。アニメーションのイージングだけを変えるときはanimation-timing-functionプロパティを使います。ここでは、「イージング関数チートシート」から、みっつ見繕ってコピペします。
やっぱり、イン・アウトしている方が自然な感じがしますねー:D。
もうちょっとヌルッとした感じを出したいので、「cubic-bezier.com」で、cubic-bezier()関数をちょこっと編集。
動きが柔らかい感じなので、線の先端も丸めたいです。線の先端の形状を指定するにはstroke-linecapプロパティを使って、丸めたいときにはround
を指定します。
で、出来上がりーXD!
@keyframes規則やanimationプロパティ、cubic-bezier()関数について、詳しくは以下のページを参照のこと。