LoginSignup
35

More than 5 years have passed since last update.

Canvasで実装するシンプルなローディング画面3パターン

Last updated at Posted at 2015-05-26

はじめに

読み込みに時間が掛かるようなコンテンツの場合、エラーでは無く読み込み中ということをユーザーに伝えるため、ローディング画面(スプラッシュ画面)を用意することはよくあるかと思います。

gifアニメーションで意図を伝えるのも良いと思いますが、できることならその読み込み状況を合わせて表示させると、よりフレンドリーかと思います。

今回はCanvasを使用して、シンプルな3種類のローディング画面を作成してみました。3種類とは単に思いついただけのものですが、基本的にはこれらの応用で色々なローディング画面を作成できるかと思います。

実際の動きは↓ページで確認ができます
http://nekoneko-wanwan.github.io/demo/canvas/loading/

使用したライブラリ

CreateJSのモジュールの一つで、色々なファイルの読み込み率が取得可能
※なおここでは使用していませんが、少なくとも画像だけであればimagesLoadedライブラリを使っても同じようなことはできるかと思います。

処理の手順

  • 読み込みとしてカウントしたい画像など、外部ファイル群を定義・取得する

・単純にソースコード内に列挙
・JSONファイル化
・documentを走査して自動的に生成する...など

  • 描画関数を定義
  • preloadJSのprogressイベントを設定(ファイルが読み込まれる度に発動)
  • progressイベント内で読み込み率を渡して実行させる描画関数を記述
  • preloadJSの実行

サンプルコード

sample.js
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画面全体に合わせることでインパクトのある表現も
  • 矩形ではなく画像を用いることでリッチな表現も

loading-kukei.gif

実装の考え方

  • A: 横・縦のサイズを読み込み率に応じて伸縮させる
  • B: 初めから横・縦の最大サイズを確保し、Canvasの領域外に配置する。読み込み率に応じてCanvas内にスライドしてくる
rect.js
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);
}

円形アニメーション

  • 円を描くようにくるっと一周させる
  • 円グラフを描くように塗りつぶす面積をどんどん増やす

loading-circle.gif

実装の考え方

  • context.arc()のstartAngle, endAngleに対し小数点を掛けあわせていく(分かりにくい...)
  • 円グラフ風にする場合は、context.moveTo()で開始点を指定する必要がある
circle.js
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)

loading-mask.gif

実装の考え方

  • 切り抜きたい形を用意し、clip()を実行した後に、アニメーションさせたい描画を定義
clip.js
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);
}

おわりに

ローディング用のアニメーションとして動きを作成してみましたが、簡単なインフォグラフィックにも使えそうです。

今まで投稿したCanvas関連の記事

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35