【JavaScript】読み込み処理でプログレスバーをアニメーションさせてみた!!

javascript

先日、CSSによるローディングバーのぐるぐるしたアニメーションに記事を書きました。

ただ、せっかくならプログレスバーで画像がどのくらい読み込まれてるか分かったほうがいいかなぁと思いましてjavascriptで複数の画像を読み込む際のプログレスバーのアニメーションを作ってみようかと思ったのでメモ。

DOM要素の取得やフェードアウトの処理などはjQueryを使いますが、プログレスバーの処理は基本的は、JavaScriptの処理だけでライブラリは使わないでいきたいと思ってます。

html要素の説明

html要素に関しては、読み込み中のアラート文他、パーセンテージや画像の読み込み数と読み込む画像を記述しています。



現在、画像を読み込み中です!

CSSの初期設定

読み込むイメージ画像

読み込むイメージ画像は、すべて読み込んでプログレスバーが100%になった後に表示させたいので、初期の段階では、displayプロパティで非表示にしておきます。


img {
    width:50px;
    display:none;
}


プログレスバーの設定

プログレスバーは、下地になるグレーのプログレスバーの上に、実際に読み込んでアニメーションするプログレスバーの設定をします。

アニメーションさせるプログレスバーは最初は、幅を0にしておきます。



#loader-wrap {
    width:100%;
    height:10px;
    background-color:#cdcdcd;
}

#loader {
    width:0px;
    height:10px;
    background-color:#17cddd;
}

JavaScriptの設定

JavaScriptでプログレスバーの読み込み処理について説明します。 変数の細かい説明やjQueryによるアニメーションなどの説明は省きます。
とりあえず、JavaScriptの全体のプログラムは下記になります。


//

var now_position=0; //プログレスバーの現在の位置
var all_img = $("img"); //すべての画像
var img_len = all_img.length; //画像の総数
var loaded_counter = 0; //読み込み完了の数値
var loading = $("#loader"); //プログレスバーの要素
var timer = null;

//アニメーションスタート
startAnime();

//
for (var i = 0; i < img_len; i++) {
    all_img[i].addEventListener("load", loadFunc);
}

//
function loadFunc() {
    //読みこんだ画像の数をカウントしておく
    loaded_counter++;
    
    $("#num").text("読み込まれた画像の数 : " + loaded_counter);
 
}

function startAnime() {
    if (!timer) {
        timer = setInterval(loadingFunc, 33);
    }
}


function stopAnime() {
  
    clearInterval(timer);
    timer = null;
    $("#res").text("読み込みが完了しました!").fadeIn(500, function () {
        $("#loader-wrap").fadeOut(1000);
        $(all_img).delay(1000).fadeIn(1500);
    });
}

//
function loadingFunc() {

    if (now_position > 99.9) {
        now_position = 100;
        stopAnime();
    }
    
     // 読み込んだ画像のパーセンテージ
  var target_position = (loaded_counter/img_len) * 100;
    //プログレスバーの目的の位置までイージングの設定
    now_position+= (target_position - now_position) * 0.2;
    $("#test").text("読み込み量:" + Math.floor(now_position));
   
    $(loading).css("width", now_position + "%");
}

タイマー設定

まずsetIntervalでタイマーの設定をして、メインとなるプログレスバーの処理であるloadingFunc関数を設定します。

startAnime();
	
function startAnime() {

    if (!timer) {
		//タイマーの設定
        timer = setInterval(loadingFunc, 33);
    }
}

イメージ画像をすべて読み込みが終わったらタイマーを解除する必要があるので、stopAnime関数でclearIntervalでタイマーを解除しておく必要があります。

function stopAnime() {

	//タイマー解除して、timer変数を空にする
	clearInterval(timer);
	timer = null;

	//その後、プログレスバーのjQuryでフェードアウトしたあとに画像を表示させる。
	$("#res").text("読み込みが完了しました!").fadeIn(500, function () {
        $("#loader-wrap").fadeOut(1000);
        $(all_img).delay(1000).fadeIn(1500);
    });
}

タイマーを解除した後は、jQueryのfadeInfadeOutでプログレスバーをフェードアウトさせて、その後画像をフェードインさせる処理をしています。

画像の読み込みのイベントを設定する

画像を読みこんだのを感知するために画像にloadイベントを設定する。

どのくらい読み込まれたか後でチェックする必要があるのでloaded_conterをカウントアップして読み混んだ画像数を変数に保存しておく。

//
for (var i = 0; i < img_len; i++) {
    all_img[i].addEventListener("load", loadFunc);
}

//
function loadFunc() {
    //読みこんだ画像の数をカウントしておく
    loaded_counter++;
    
    $("#num").text("読み込まれた画像の数 : " + loaded_counter);
 
}

プログレスバーのアニメーションの処理

いよいよメインとなるJavaScriptでプログレスバーのアニメーションの処理である関数のloadingFuncの説明です。

読み込んだイメージ画像のパーセンテージ

読みこんだイメージ画像が、イメージ画像の総数のどのくらいのパーセンテージになるのかは、読み込まれたイメージ画像の数を総数で割った値に100をかけることでパーセンテージの数値を出すことができます。

  // 読み込んだ画像のパーセンテージ
  var target_position = (loaded_counter/img_len) * 100;

プログレスバーの目的の幅の位置までイージングの処理

読みこんだパーセンテージの値を割り出したらそれが、プログレスバーがアニメーションする目的の幅となります。

で、イージングさせるには、ActionScriptで良く使われていた公式があります。

オブジェクトの現在座標 +=( 目的地の座標 - オブジェクトの現在の座標 ) * 減速係数

もう有名な公式があるのでそれに当てはめればいいので、プログレスバーの目的となる幅から現在のプログレスバー幅を差し引いた値に減速係数をかけた値をまた、現在のプログレスバー幅に加算してあげることでイージングになります。

  //プログレスバーの目的の位置までイージングの設定
    now_position+= (target_position - now_position) * 0.2;
	$("#test").text("読み込み量:" + Math.floor(now_position));

最後に、その数値を「〇〇%」とページ上で表示させたいので、jQueryのtextメソッドで表示させています。
その際に、小数点以下を省きたいのでMath.floor関数で小数点以下を切り捨てています。

プログレスバーの幅を設定する

プログレスバーの目的となる幅を割り出したら、そいつをCSSで設定してあげます。今回はjQueryのCSSプロパティを使いました。

値を設定するときは、パーセンテージ(%)で設定するのを忘れずに!!

$(loading).css("width", now_position + "%");

アニメーションを止める処理

イメージ画像をすべて読み込んだら、プログレスバーが100%になった時点でアニメーションを解除したいのですが、その前にif文で下記の処理が必要になります。


	if (now_position > 99.9) {
        now_position = 100;
        stopAnime();
    }
	

なぜかというとイージングで減速させる式を使うと、だんだん100%に近づきますがいつまで経っても100%にならないというパラドックス(矛盾)が発生します。これは、もうプログラムのそういう仕様です。その為if文を使って今回は99.9パーセントになったら、プログレスバーの幅を100%にするという記述をしています。そこで初めてstopAnime関数を実行します。

stopAnimeが実行されたら、プログレスバーがフェードアウトして、画像が表示されるようになります。

まとめ

というよにJavaScritpによるプログレスバーで画像を読み込むアニメーションをやってみましたが、ライブラリも探せばあるだろうし、イージングなんてjQueryのanimateを使ったりeasingライブラリを使えば簡単だと思います。
けど、こういったライブラリを使わない処理もJavaScriptを知る意味では勉強になると思います。といってもちょこちょこjQueryは使いましたが(笑)