jQueryで実装するページローディングのプログレスバー
今回は、ページの読み込み時、jQueryを使い進捗状況をプログレスバーで表示する方法を、実際にサンプルコードを用いて、詳しく記載していこうと思います。
ページを読み込む際、jQueryでページローディングを実装しているサイトをよく見かけますが、プログレスバーを実装しているサイトは少ないように感じます。そこで、今回記載する「プログレスバーでの表示機能」を用意しておくと、ページローディングと同様に、すべての画像の準備が整うのを待ってから、ページを表示することができます。画像をたくさん含むページやファイルサイズの大きいページに、ページローディングのUIとして実装することをおすすめします。
という事で、それでは今回はッ、
- ・プログレスバー表示機能の概要
- ・プログレスバー表示に必要な処理
- ・プログレスバー表示のHTMLとCSS
- ・プログレス、ローディング表示のjQuery
上記について記載していこうと思います…。
プログレスバー表示機能の概要
Webページを構成する画像の枚数が多く、ページファイルの読み込みに多少時間がかかりそうな場合など、すべての画像の準備が整うのを待ってからコンテンツを表示したいことがあります。
そのような場合は、画像の読み込みが完了するまでコンテンツを一時的に隠しておき、その間はプログレスバーの表示によって画像の読み込み状況をリアルタイムでユーザーに伝える方法が効果的なことと思います。
今回記載するプログレス表示は「読み込み状況を表すプログレスバー」と「パーセンテージを示すテキスト」から構成されるよう作成しました。このプログレス表示は画面全体を覆うオーバーレイの上に表示し、すべての画像の読み込みが完了した時点で画面外にスライドさせています。
このようなローディング表示により、ユーザーに対して読み込み途中の画像を見せることなく、処理が進行していることを通知できるので、安心感を与えることができます。また、効果的なアニメーションにより、待ち時間が実際よりも短く感じる効果も期待できます。大きな画像を扱う必要がある場面では導入することをおすすめします。
プログレスバー表示に必要な処理
プログレスバー表示を実現するには、主に以下の処理が必要になります。
- ・画像の読み込み状況を常に監視する処理
- ・読み込み状況をプログレスバーとテキストにリアルタイムで反映する処理
- ・読み込みが完了した時点で、プログレス表示を非表示にする処理
ここでは「状況を常に監視し、その結果をリアルタイムで表示に反映」という点がポイントになります。この画像の読み込み状況を把握する処理を実装するには、下記に紹介する「imagesLoaded」(ライブラリ)がおすすめで、今回はコチラのCDNを使用しています。
プログレスバー表示のHTMLとCSS
今回記載するプログレス表示はデザインがシンプルなので、HTMLとCSSには特に難しい個所はありません。初期状態ではテキストの内容とプログレスバーの幅はともに0%です。これらをjQueryで書き換えていくことになります。
<span class=”progress_bar”></span>
<span class=”progress_text”>0%</span>
</div>
.progress { |
background-color: rgb(76, 84, 130); |
color: rgb(255, 255, 255); |
height: 100%; |
position: absolute; |
width: 100%; |
} |
.progress_bar { |
border-top: 1px solid rgb(160, 160, 160); |
position: absolute; |
top:50%; |
width: 0%; |
} |
.progress_text { |
font-family: “Menlo”, “Consolas”, monospace; |
font-size: 13px; |
margin-top: 10px; |
position: absolute; |
text-align: center; |
top: 50%; |
width: 100%; |
} |
.progress_complete .progress_bar { |
border-top-color: rgb(255, 255, 255); |
} |
上記CSSのうち、.progress_completeクラスの指定は、プログレス表示が「100%」の状態になった際に適用するスタイルです。
初期状態では、HTMLにこのクラスはマークアップされていませんが、プログレス表示の処理が完了した時点でjQueryによって追加されます。
プログレス、ローディング表示のjQuery
それでは、jQueryのコードを記述してみます。
imagesProgress();
function imagesProgress () {
var container = $(‘#progress’),
progressBar = container.find(‘.progress_bar’),
progressText = container.find(‘.progress_text’),
imgLoad = imagesLoaded(‘body’),
imgTotal = imgLoad.images.length,
imgLoaded = 0,
current = 0,
progressTimer = setInterval(updateProgress, 1000 / 60);
imgLoad.on(‘progress’, function () {
imgLoaded++;
});
function updateProgress () {
var target = (imgLoaded / imgTotal) * 100;
current += (target – current) * 0.1;
progressBar.css({ width: current + ‘%’ });
progressText.text(Math.floor(current) + ‘%’);
if(current >= 100){
clearInterval(progressTimer);
container.addClass(‘progress_complete’);
progressBar.add(progressText)
.delay(500)
.animate({ opacity: 0 }, 250, function () {
container.animate({ top: ‘-100%’ }, 500);
});
}
if (current > 99.9) {
current = 100;
}
}
}
});
コード量はさほど多くありませんが、多少複雑に見えるかもしれません。
しかし、このコードは特にアニメーションの基本を学ぶには良いサンプルかと思います。
表示に必要な要素をjQueryオブジェクトに
初めにプログレス表示に必要な要素をHTMLから取得して、jQueryオブジェクトに変換します。
■ 必要な要素をjQueryオブジェクトに
var container = $(‘#progress’),
progressBar = container.find(‘.progress_bar’),
progressText = container.find(‘.progress_text’),
変数containerにはプログレス表示全体を、変数progressBarにはその子要素のバー部分を、変数progressTextにはその子要素のテキスト部分を格納しています。
画像の読み込み状況の監視とプログレス表示への反映
次に必要になってくるのは「画像の総数」と「読み込みが完了した画像の点数」をリアルタイムで把握し、それをプログレス表示へ刃ね居させる仕組みです。そのためにここでは上記で紹介いたしましたimagesLoadedライブラリを使用してその値を取得します。
■ 画像の読み込み状況の監視とプログレス表示への反映
// imagesLoaded ライブラリで body 要素内の画像の読み込み状況を監視
// 同時に body 全体の画像の総数を保存
imgLoad = imagesLoaded(‘body’),——①
imgTotal = imgLoad.images.length,——②
// 読み込みの完了した画像の数のカウンターと、
// プログレス表示の現在地にあたる数値 (ともに最初は 0)
imgLoaded = 0,——③
current = 0,——③
// 1 秒間に 60 回のペースで読み込み状況をチェック
progressTimer = setInterval(updateProgress, 1000 / 60);——④
// imagesLoaded を利用し、画像が読み込まれるごとにカウンターを加算
imgLoad.on(‘progress’, function () {——⑤
imgLoaded++;——⑤
});
まず、imagesLoadedをimagesLoaded(‘body’)という形式で呼び出し、変数imgLoadに格納します①。これは(‘body’)という形式でjQueryオブジェクトを作成するのと同様、「imagesLoadedオブジェクトを作成している」と考えてください。
画像の総数の取得
imagesLoadedオブジェクトには、imagesというプロパティがあり、要素内の配列が格納されています。そのため、imgTotal = imgLoad.images.lengthを記述することで、body要素内の「画像の総数」を変数imgTotalに格納できます②。
読み込みが完了した画像点数とプログレス現在地にあたる数値
続いて宣言している変数imgLoadedと変数currentは、それぞれ「読み込みが完了した画像の点数」と「プログレス表示の現在地にあたる数値」を格納するための変数です。初期値は共に「0」です③。ここの値を順次更新することで、プログレス表示を変更します。
読みこみ状況の確認
変数ProgressTimerには「画像の読み込み状況を監視するためのタイマー」が格納されています④。このタイマーはsetInterval()関数によって1/60秒ごと、つまり1秒間に60回のペースで更新されます。setInterval()関数に渡しているupdareProgress()関数は、このサンプルで独自に定義しているオリジナルの関数で、「現在の読み込み状況をもとにしてプログレス表示を更新する関数」です。つまり、変数progressTimerは「1秒間に60回のペースで画像を読みこみをチェックし、プログレス表示を更新する」ためのタイマーということになります。
読み込みが完了した画像の点数の更新
変数imaLoadedの値はどうして更新されるのでしょうか。これには「progress」というイベントを使用しています。
imagesLoadedオブジェクトでは1点1点の画像の読み込みが完了するたびに「progress」というイベントが自動的に発生します。そこでこれを利用して、変数imgLoadedの値を随時更新していきます⑤。imagesLoadedオブジェクトのイベントは上記のようにjQueryと似たon()メソッドでイベントハンドラを登録できます。
これでプログレス表示に必要な「画像の総数」と「読み込みが完了した画像の点数」という2つのデータを取得できたことになります。
画像の読み込み状況をプログレス表示に反映する
「画像の総数」と「読み込みが完了した画像の点数」の2つが分かれば全体のパーセンテージ値を求められるので、これらの値だけでプログレス表示が可能ですが、プログレス表示を滑らかに変化させるためには、画像の読みこむタイミングよりも細かいタイミングで、連続して表示を更新する必要があります。そこで、画像の読み込み状況を表示に反映させる関数(updateProgress()関数)を新たに用意しています。この関数は上記で記載いたしました通り、1秒間に60回のペースで実行されます。
■ updateProgress関数
function updateProgress () {
// 読み込みの完了した画像のパーセンテージ
var target = (imgLoaded / imgTotal) * 100;——①
// current (現在地) と target (目的地) の距離をもとにイージングをかける
current += (target – current) * 0.1;——②
// 表示のバーの幅とテキストに current の値を反映
// テキストは小数点以下を切り捨てて整数に
progressBar.css({ width: current + ‘%’ });——③
progressText.text(Math.floor(current) + ‘%’);——③
updateProgress()関数では、最初に(imgLoaded / imgTotal) * 100という値を変数targetに格納しています①。変数imgLoadedには「読み込みが完了した画像の点数」、変数imgTotalには「画像の総数」が格納されているので、変数targetには「その時点での画像の読み込み状況をパーセンテージで表した数値」が格納されます。
この変数targetの値をそのまま表示に反映させると、カクカクした動きになってしまうので、「イージングの公式」を利用してこの値を加工します。加工後の値は事前に用意しておいた変数currentに格納します②。
ここではイージング効果を上記の公式を用いて実現しています。
変数currentが「現在地の座標」、変数targetが「目的地の座標」にあたります。イージング係数は0~1までの少数で指定し、大きいほど早く動きます。上記では0.1という数値を指定していますが、これはつまり、現在地からの目的地に向かって距離を縮めていくとき、「残りの距離の1/10ずつ進む」ということになります。
また、updateProgress()関数では、変数currentの値を算出すると同時に、プログレスバーのCSSとテキストを書き換えています③。これが1秒間に60回という速いペースで実行されるため、プログレス表示が滑らかに変化しているように見えます。
なお、テキストを書き換える際、変数currentの値にMath.floor()メソッドを使っています。このメソッドは「小数点以下を切り捨てた変数を返すメソッド」です。変数currentの値は、大変細かい小数値になるので、このメソッドを使用しています。
プログレス表示の終了処理
最後に必要なのは、プログレス表示が「100%」になった時点(すべての画像が読みこみ終わった時点)で、プログレス表示を終了する処理になります。この処理は変数currentの値が「100」を超えた際に実行します。
■ プログレス表示の終了処理
if(current >= 100){
// プログレス表示の更新をストップ
clearInterval(progressTimer);——①
// CSS でスタイルを変えるためクラスを追加
container.addClass(‘progress_complete’);——②
// プログレスバーとテキストを同時にアニメーションさせるため、
// グループ化して 1 つの jQuery オブジェクトに
progressBar.add(progressText)——③
// 0.5 秒待つ
.delay(500)
// 0.25 秒かけてプログレスバーとテキストを透明にする
.animate({ opacity: 0 }, 250, function () {——④
// 0.5 秒かけてオーバーレイを上方向へスライドアウト
container.animate({ top: ‘-100%’ }, 500,);
});
}
// current が 99.9 より大きければ 100 と見なして終了処理へ
if (current > 99.9) {——⑤
current = 100;
}
まず、clearInterval()メソッドを呼び出して、updateProgress()関数を呼び出していたタイマーをとめます①。
次に、addClass()メソッドを使用してHTMLに.progress_completeクラスを追加しています②。addClass()メソッドは「処理対象のjQueryオブジェクトに任意のクラスを追加するメソッド」です。このクラスにはプログレス表示が完了した際のスタイルが指定されています。
続いて、プログレスバーとテキストに対して同時にアニメーション処理を適用するために、add()メソッドを使用して2つめのjQueryオブジェクトをグループ化しています③。add()メソッドは「すでに選択しているjQueryオブジェクトに対し、さらに新しくjQueryオブジェクトを追加するメソッド」です。ここでは変数progressBarと変数progressTextに格納されている2つめのjQueryオブジェクトを1つのjQueryオブジェクトとして扱えるようにしています。
グループ化したjQueryオブジェクトに対して、ますはdelay()メソッドを利用して0.5秒間はそのままの状態で待機させています。delay()メソッドは「アニメーションの開始を遅らせるメソッド」です。引数には「遅らせる時間」をミリ秒で指定します。
0.5秒経過したらanimate()メソッドを使用して、0.25秒かけてフェードアウトさせます。
ここでanimate()メソッドの引数に関数を渡している点に注目してください④。この関数はアニメーションが完了した時点で呼び出されます。この関数には、プログレス表示のオーバーレイを1秒かけて上方向にスライドアウトさせる処理が指定されています。
上記の処理をまとめると、プログレス表示が100%になったら以下の処理を連続して実行するということになります。
① 0.5秒待つ
② 0.25秒かけてプログレスバーとテキストをフェードアウト
③ 0.5秒かけてオーバーレイを上方向にスライドアウト
なお、プログレス表示のもとになる変数currentの値は、イージングの公式の性質により厳密には「100」に到達しません。そこで、99.9%を超えた時点で100%に到達したとみなすために、関数の最後に変数currentに「100」を代入する処理の記述をしています⑤。
ということで今回は、jQueryで実装するページローディングのプログレスバーの実装方法につきまして、サンプルコードを交え記載いたしました。
jQuery初心者の方には、少し難しい内容だったことと思います。と、ここで以前記載した内容を再度記載いたしますと、「難しいことは、部分部分また、パーツごとに分けて考える!」これが重要なように思います。今回ご紹介したjQueryの内容も、部分部分に分けて考えると、比較的分かりやすく理解できることと思います。要は「焦らず・じっくり・ゆっくりと」になります。
とりあえず、今回はここまで…。
お仕事のご依頼は↓コチラより…、それではまた次回…。