株式会社アビストAIソリューション事業部 AI-Plant Bamboo 開発チームの杉山です。
AI-Plant Bambooは、機械学習プラットフォームという特性上、データの読み込みやモデルの作成の段階でユーザーを待たせてしまう場面があります。
開発エンジニアとして、こうした待ち時間を減らすことに注力しますが、設計やリソースの都合上、どうしても待ち時間を短縮できない場合があります。
このような待ち時間が発生する場面では「操作を間違ったかもしれない」「壊してしまったかもしれない」といったユーザーの不安を取り除くことが大切です。
ユーザーの不安を軽減する方法の1つとして「ローディングアニメーションを表示する」というものがあります。ローディングアニメーションを表示することによって「アプリケーションが動作している」ということを視覚的に表現しつつ「いまは待つ時間だよ」ということをユーザーに伝えることができます。
今回は、HTMLとCSSだけで簡単に実装できるローディングアニメーションを作ってみました。 CSSでアニメーションを作る基本的な方法から、ローディングアニメーションの実装方法まで、分かりやすく紹介しますので「CSSでアニメーションを作ってみたい」という方は、ぜひ気軽に試してみてください。
0. 対象とする読者
- CSSでアニメーションを作ってみたい方
- JavaScriptを使わずにアニメーションを作りたい方
- ローディングアニメーションの実装例を見たい方
1. CSSで作るローディングアニメーション
Webアプリケーション上でアニメーションを表示する方法としては「JavaScriptを使用する方法」や「GIF画像を作成して埋め込む方法」など、いくつかありますが、CSSを使用して作る方法はとても簡単です。
今回は、CSSとHTMLで、以下のようなローディングアニメーションを作成します。
2. CSSアニメーションの作り方
CSSでは@keyframesという@-規則を利用して作成します。 「@-規則」はCSSの動作を規定するものです。
@keyframesを使用すると、アニメーションのキーフレームを定義できます。
キーフレームは、アニメーションの主要な変化を定義するフレームで、アニメーションの変化点における要素のスタイルを定義します。 アニメーションが実行される際に、変化点から変化点に、定義したスタイルをなめらかにつなぐように描画されます。
@keyframes アニメーションの名前 { 0% { /* アニメーションの開始時のスタイルを記述する */ } 50% { /* アニメーションが50%進行した状態のスタイルを記述する */ } 100% { /* アニメーションの終了時のスタイルを記述する */ } }
上記の @keyframes には「開始時点」「50%進行した時点」「終了時点」のキーフレームを定義した例を示しています。
実例を見たほうが分かりやすいと思いますので、例として「正方形の箱が右方向にスライドするアニメーション」を作ってみましょう。
<div id="object"></div>
#object { animation: 2s slide; background-color: green; height: 40px; width: 40px; } @keyframes slide { 0% { transform: translateX(0); } 100% { transform: translateX(100px); } }
ここでは0%(開始状態)のスタイルと100%(終了状態)のスタイルを定義しています。
transformは、指定した要素を変形したり移動したりできるプロパティです。 translateX(移動距離)を記述することによって、要素がX軸方向に移動します。
このアニメーションは以下のように表示されます。
緑色の四角形が画面右方向に連続的に移動します。 さらに、以下のように、スタイルを追加することによって、色を変えたり、回転を加えることもできます。
#object { animation: 2s slide; background-color: green; height: 40px; width: 40px; } @keyframes slide { 0% { background-color: blue; transform: translateX(0); } 100% { background-color: green; transform: translateX(100px) rotateZ(90deg); } }
このように、キーフレームごとにスタイルを記述することによって、複雑なアニメーションを実現できます。
3. CSSアニメーションを要素に適用する
上記のようにして定義したアニメーションは、animationプロパティを通じて、指定した要素に適用できます。 例えば、以下のようなHTMLがあり、id="object"の要素に対してアニメーションを適用したいとします。
<div id="container"> <div id="object"></div> </div>
このとき、#objectに対して以下のようなスタイルを定義することによって、アニメーションを適用できます。
#object { animation: [アニメーションの名前] [アニメーションの時間]; }
たとえば slide という名前のアニメーションを1秒間実行するには、以下のようにスタイルを記述します。
#object { animation: slide 1s; }
4. ローディングアニメーションを作ろう
それでは、この記事のテーマである、ローディングアニメーションを作りましょう。
今回は、以下のようなアニメーションを作成します。
4本のバーが下から階段状に現れ、4本のバーが同じ高さに揃った後で同じ高さに集合し、もとに戻る、というシンプルなローディングアニメーションです。
4.1. HTMLを設置する
まず、HTMLを記述します。アニメーション自体が入るコンテナと、その内側に4本のバーを配置します。 それぞれcontainerクラスとbarクラスを付与します。
<div class="container"> <div class="bar"></div> <div class="bar"></div> <div class="bar"></div> <div class="bar"></div> </div>
4.2. 基本のスタイルを記述する
次に、アニメーションのない初期状態で適用するスタイルを記述します。
.container { height: 200px; position: relative; width: 200px; } .bar { background-color: #37A372; bottom: 0; height: 100px; position: absolute; transform-origin: center bottom; width: 20px; }
バーの大きさは、幅を20px、高さを100pxとしました。
transform-origin は、後にそれぞれのバーにtransformプロパティで指定する変形方法について、変形の原点を指定するプロパティです。
{ transform-origin: center bottom; }
この例の場合、水平方向についてはcenterが、垂直方向についてはbottomが変形の原点となります。 これによって、アニメーションの実行時にバーが下側から出てくるようになります。
続いて、4本のそれぞれのバーにスタイルを記述します。 4本のバーが左から順に5px間隔で配置されるようにしました。
:nth-child() は擬似クラスで、兄弟要素について位置を指定して、スタイルを記述できます。
.bar:nth-child(1) { left: calc(25px * 1); } .bar:nth-child(2) { left: calc(25px * 2); } .bar:nth-child(3) { left: calc(25px * 3); } .bar:nth-child(4) { left: calc(25px * 4); }
calc() 関数を使用すると「25px * 2」のようにプロパティの値を計算によって指定できます。
ここまでのHTMLとCSSで、以下のように表示されます。
4.3. アニメーションを記述する
さて、いよいよアニメーションを記述します。
4本のバーについて、それぞれタイミングを変えて動かすため、それぞれのバーについて@keyframesを定義して適用します。
@keyframes expand_bar_1 { /* 左から1本目のバーに適用するアニメーションを記述 */ } @keyframes expand_bar_2 { /* 左から2本目のバーに適用するアニメーションを記述 */ } @keyframes expand_bar_3 { /* 左から3本目のバーに適用するアニメーションを記述 */ } @keyframes expand_bar_4 { /* 左から4本目のバーに適用するアニメーションを記述 */ }
また、今回作成するアニメーションは6つのステップに分割できます。
1. 1本目のバーが生える 2. 2本目のバーが生える 3. 3本目のバーが生える 4. 4本目のバーが生える 5. 全てのバーの高さがそろう 6. 全てのバーが引っ込む
@keyframesには、0~100%で値を指定してキーフレームを定義する必要があるため、アニメーションを6つに分割し、以下の変化点でキーフレームを定義します。
1. 1番目のバーが生える (~16%) 2. 2番目のバーが生える (~32%) 3. 3番目のバーが生える (~48%) 4. 4番目のバーが生える (~64%) 5. 全てのバーの高さがそろう (~80%) 6. 全てのバーが引っ込む (~100%)
各バーの@keyframesは、以下のような構造になります。
@keyframes expand_bar_#num { 0% { /* 開始状態のスタイルを記述 */ } 16% { /* ステップ1の状態のスタイルを記述 */ } 32% { /* ステップ2の状態のスタイルを記述 */ } 48% { /* ステップ3の状態のスタイルを記述 */ } 64% { /* ステップ4の状態のスタイルを記述 */ } 80% { /* ステップ5の状態のスタイルを記述 */ } 100% { /* ステップ6の状態のスタイルを記述 */ } }
アニメーションの各ステップにおいて、変化するスタイルは各バーの「高さ」だけです。 高さはtransformプロパティのscaleY()関数を用いて、縮尺比率で定義します。
{ transform: scaleY(Y軸方向の縮尺比率); }
以上を踏まえて、各バーの@keyframesを記述すると以下のようになります。
@keyframes expand_bar_1 { 0% { transform: scaleY(0); } 16% { transform: scaleY(0.25); } 32% { transform: scaleY(0.25); } 48% { transform: scaleY(0.25); } 64% { transform: scaleY(0.25); } 80% { transform: scaleY(0.5); } 100% { transform: scaleY(0); } } @keyframes expand_bar_2 { 0% { transform: scaleY(0); } 16% { transform: scaleY(0); } 32% { transform: scaleY(0.5); } 48% { transform: scaleY(0.5); } 64% { transform: scaleY(0.5); } 80% { transform: scaleY(0.5); } 100% { transform: scaleY(0); } } @keyframes expand_bar_3 { 0% { transform: scaleY(0); } 16% { transform: scaleY(0); } 32% { transform: scaleY(0); } 48% { transform: scaleY(0.75); } 64% { transform: scaleY(0.75); } 80% { transform: scaleY(0.5); } 100% { transform: scaleY(0); } } @keyframes expand_bar_4 { 0% { transform: scaleY(0); } 16% { transform: scaleY(0); } 32% { transform: scaleY(0); } 48% { transform: scaleY(0); } 64% { transform: scaleY(1); } 80% { transform: scaleY(0.5); } 100% { transform: scaleY(0); } }
4.4. アニメーションを適用する
最後に、これらの@keyframesを各バーに対して適用しましょう。 animationプロパティを介して適用します。
{ animation: 6s expand_bar_#num ease infinite; }
1ステップあたり約1秒のアニメーションにしたいので、アニメーションの継続時間を 6(ステップ) x 1(秒) = 6(秒) とします。
また、ease(animation-timing-function)を指定することによって、各キーフレームの動作がなめらかになります。
さらに、infinite(animation-iteration-count)を指定することによって、アニメーションが繰り返し実行されます。 今回はローディングアニメーションであり、処理が終わるまで繰り返し動作させたいのでinfiniteを指定しました。
.bar:nth-child(1) { animation: 6s expand_bar_1 ease infinite; left: calc(25px * 1); } .bar:nth-child(2) { animation: 6s expand_bar_2 ease infinite; left: calc(25px * 2); } .bar:nth-child(3) { animation: 6s expand_bar_3 ease infinite; left: calc(25px * 3); } .bar:nth-child(4) { animation: 6s expand_bar_4 ease infinite; left: calc(25px * 4); }
こうして、以下のようなローディングアニメーションができました。
5. まとめ
今回はCSSとHTMLだけで作れるローディングアニメーションを実装しました。 CSSだけでもそれなりに動くアニメーションを作れることが分かっていただけたかと思います。
ピュアなCSSを用いたため、繰り返し記述が必要な部分がありました。 Sass等を使えばより少ない記述で書けるかもしれません。
株式会社アビストAIソリューション事業部では、このような技術者向けの記事を今後も公開する予定です。 Twitterもやっていますので、ぜひフォローしてください。
「こんなアニメーションを作ってみました」とか「こうするともっときれいに実装できるよ」といったコメントもお待ちしております。
AIソリューション事業部 公式Twitterアカウント @abist_ai