はじめに
読み込みに時間が掛かるようなコンテンツの場合、エラーでは無く読み込み中ということをユーザーに伝えるため、ローディング画面(スプラッシュ画面)を用意することはよくあるかと思います。
gifアニメーションで意図を伝えるのも良いと思いますが、できることならその読み込み状況を合わせて表示させると、よりフレンドリーかと思います。
今回はCanvasを使用して、シンプルな__3種類のローディング画面__を作成してみました。3種類とは単に思いついただけのものですが、基本的にはこれらの応用で色々なローディング画面を作成できるかと思います。
実際の動きは↓ページで確認ができます
http://nekoneko-wanwan.github.io/demo/canvas/loading/
使用したライブラリ
CreateJSのモジュールの一つで、色々なファイルの読み込み率が取得可能
※なおここでは使用していませんが、少なくとも画像だけであればimagesLoadedライブラリを使っても同じようなことはできるかと思います。
処理の手順
- 読み込みとしてカウントしたい画像など、外部ファイル群を定義・取得する
・単純にソースコード内に列挙
・JSONファイル化
・documentを走査して自動的に生成する...など
- 描画関数を定義
- preloadJSのprogressイベントを設定(ファイルが読み込まれる度に発動)
- progressイベント内で読み込み率を渡して実行させる描画関数を記述
- preloadJSの実行
サンプルコード
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
/* 読み込みファイルの定義 */
var images = [
{src: 'img/ph01.jpg'},
{src: 'img/ph02.jpg'}
];
/**
* 描画関数の定義
* @param zero_point 0.01 ~ 1.00の値を渡す
*/
function draw(zero_point) {
var percentage = (zero_point * 100).toFixed(0); // 0 ~ 100%に変換
ctx.clearRect(0, 0, canvas.width, canvas.height);
// zero_point や percentageを使って描画する
// ...
}
/* preloadJSの定義 */
var preload = new createjs.LoadQueue();
/* 同時読み込み数の設定(デフォルトは1) */
preload.setMaxConnections(1);
/* progressイベント */
preload.on("progress", function(e) {
var zero_point = (e.progress).toFixed(2); // 小数点第二位まで 0.01 ~ 1.00
draw(zero_point); // 描画関数を実行
if (e.progress === 1) {} // 完了したら特定の処理を行うことも
});
/* 定義した外部ファイル群を読み込む。falseで実行を保留できる */
preload.loadManifest(images, false);
/* 保留にした場合の実行トリガー */
preload.load();
3種類のローディング画面
矩形アニメーション
- 棒グラフのように読み込み率に合わせて矩形をぐぐーっと伸ばす
- 矩形サイズをCanvas画面全体に合わせることでインパクトのある表現も
- 矩形ではなく画像を用いることでリッチな表現も
実装の考え方
- A: 横・縦のサイズを読み込み率に応じて伸縮させる
- B: 初めから横・縦の最大サイズを確保し、Canvasの領域外に配置する。読み込み率に応じてCanvas内にスライドしてくる
function draw() {
var percentage = (zero_point * 100).toFixed(0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
// メインの矩形描画
ctx.beginPath();
ctx.fillStyle = "#000000";
// A
ctx.fillRect(0, 0, percentage, 7);
// B
ctx.fillRect(0, canvas.height - (canvas.height * zero_point), canvas.width, canvas.height);
// テキスト
ctx.font = "18px 'MS Pゴシック'";
ctx.fillStyle = "#ffffff";
ctx.fillText(percentage + '%', 0, 40);
}
円形アニメーション
- 円を描くようにくるっと一周させる
- 円グラフを描くように塗りつぶす面積をどんどん増やす
実装の考え方
- context.arc()のstartAngle, endAngleに対し小数点を掛けあわせていく(分かりにくい...)
- 円グラフ風にする場合は、context.moveTo()で開始点を指定する必要がある
function draw() {
var percentage = (zero_point * 100).toFixed(0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 円周を描く
ctx.beginPath();
ctx.lineWidth = 5;
ctx.arc(70, 70, 60, Math.PI * 1.5, Math.PI * 2 * zero_point + Math.PI * 1.5, false);
ctx.stroke();
// 円グラフを描く
ctx.beginPath();
ctx.moveTo(70, 70);
ctx.lineWidth = 5;
ctx.arc(70, 70, 60, Math.PI * 1.5, Math.PI * 2 * zero_point + Math.PI * 1.5, false);
ctx.fill();
}
マスクアニメーション
- 任意の形を用意し、そのシェイプで切り抜くことでインパクトのある表現が可能(コンセプトやキャラクターのシェイプを用いることでよりコンテンツの雰囲気が出せる)
- 複雑なシェイプを用意するのが大変なのはまた別問題...
切り抜く形までもアニメーションをさせたら、描画残像が汚く残ってしまいました...(chrome)
実装の考え方
- 切り抜きたい形を用意し、clip()を実行した後に、アニメーションさせたい描画を定義
function draw() {
var percentage = (zero_point * 100).toFixed(0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 切り抜く形を定義
ctx.beginPath();
ctx.arc(70, 70, 60, 0, Math.PI * 2, false);
ctx.stroke();
// クリップ実行
ctx.clip();
// ただの矩形だがクリッピングされて円形となる
ctx.beginPath();
ctx.fillStyle = "#000000";
ctx.fillRect(0, canvas.height - (canvas.height * zero_point), canvas.width, canvas.height);
}
おわりに
ローディング用のアニメーションとして動きを作成してみましたが、簡単なインフォグラフィックにも使えそうです。