ページのローディング中にPACEプラグインでプログレスバーを表示する【Javascript/CSS】

css

表示に時間がかかるような重いページを開く時、プログレスバーなどで読み込み状況を表示させるとページ離脱防止になります。今回、お手軽にプラグインで実装したのでメモ。

PACEプラグインでプログレスバーを表示

設置は簡単で、以下コードをheadタグ内に追加するだけです!コードは公式のデモページに記載されています。これだけで動作します。

<script src="https://cdn.jsdelivr.net/npm/pace-js@latest/pace.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pace-js@latest/pace-theme-default.min.css">

表示されるローディングアイコンもテーマとしていくつか用意されています。
使用したいアイコンのDONWLOADをクリックすると、CSSがダウンロードできます。

今回、「Corner Indicator」というアイコンを反映してみます。

DOWNLOADをクリックするとCSSをダウンロードできる

corner-indicator.cssがダウンロードできたので、このファイルをHTMLで読み込みます。
反映したのがこちらです。

See the Pen pace-progress by donguri2020 (@m-ke) on CodePen.

画像が表示されるまでの間、設定したアイコンが表示され、画像の読み込みが完了したらアイコンは非表示になります。
繰り返し確認したい場合は、CodePenの「return」ボタンをクリックしてください。

表示をカスタマイズする

これで希望した動きは実装できましたが、ちょっと動きが物足りない。。のでカスタマイズします。
カスタマイズしたい内容は次の3点です。尚、先ほど読み込んだcorner-indicator.cssは外して実装します。

  • ページの読み込みがすべて完了したら上から画像をフワッと表示させたい。
  • プログレスバーのデザインを公式以外のものに変更したい。
  • 読み込み状況をパーセントで表示したい。

カスタマイズしたものがこちらです。

実際の動作はこちらでご確認ください!(別ウィンドウが開きます)
注)容量の重いページになっています。

ページの読み込みがすべて完了したら上から画像をフワッと表示させる

読み込み完了の判定方法

最初、画像は非表示にしておいて、ページの読み込みがすべて完了したら表示させます。
読み込み状況は、PACEプラグインによって追加されるクラス名で判定できます。

デベロッパーツールで確認すると、body直下にプログレスバーを表示する要素pace-inactiveが追加されています。
そして、bodyタグにもpace-runningというクラス名が追加されています。

ページの読み込みが完了すると、以下のようにクラス名が変わります。これを読み込み完了の判定に使います。

bodyタグのクラスは次のように変わります。
pace-running → 読み込み中
pace-done → 読み込み完了

追加されたプログレスバーの要素は次のように変わります。
pace-inactive → 読み込み中
pace-active→ 読み込み完了

CSSでアニメーションさせる

先程のクラス名を使ってCSSを次のように設定します。

/* ページ読み込みアニメーション */
.gallery img {
  opacity: 0;
  transform: translateY(-10%);
  transition: opacity 1s, transform 1s;
}
.pace-done .gallery img {
  opacity: 1;
  transform: translateY(0);
}

初期値として、画像に透明度0、表示位置をY軸に-10%、アニメーションさせたいのでtransitionを設定します。
pace-doneが付与されたら透明度、表示位置を元に戻します。
これで上からフワッと現れる動きが実装できました。

プログレスバーのデザインを公式以外のものに変更したい。

公式のプログレスバー以外のデザインを使いたい場合もあると思います。
今回、こちらのアイコンを反映したいと思います。

ローティングアイコンはこちらのサイトからお借りしました。

https://connoratherton.com/loaders

使用する際は、Githubでデータをダウンロードしておきます。

GitHub - ConnorAtherton/loaders.css: Delightful, performance-focused pure css loading animations.
Delightful, performance-focused pure css loading animations. - ConnorAtherton/loaders.css


linkタグで任意のディレクトリに、先ほど保存したCSSを読み込みます。

<link href="<任意のディレクトリ>/loaders.min.css" rel="stylesheet">

設置したいアイコンのタグはこのような構造になっています。

<div class="ball-scale-multiple">
    <div></div>
    <div></div>
    <div></div>
</div>

このタグをPACEプラグインで追加されたプログレスバーの要素の中に追加すれば良さそうです。

MutationObserverでDOMを監視する

プログレスバーを表示する要素の構造は次のようになっています。

<div class="pace pace-inactive">
    <div class="pace-progress" data-progress-text="100%" data-progress="99" style="transform: translate3d(100%, 0px, 0px);">
        //ローディングアイコンのタグを追加
    </div>
</div>

ローディングアイコンのタグは、pace-progressタグの中にjavascriptを使って追加したいと思います。
当たり前ですが、PACEプラグインが読み込まれる前に追加しようとするとエラーになります。
そこで、DOMの動きを監視しpace-progressが存在することを確認してからタグを挿入します。

DOMの監視はMutationObserverで可能です。
今回の場合、コードはこんなカンジになります。

//監視したい要素
const targetElm = document.querySelector('body');

//DOMが変更したら実行する関数
function addProgress() {
    //pace-progressがあったら
    if(document.querySelector(".pace-progress") != null) {
    document.querySelector(".pace-progress").innerHTML = '<div class="ball-scale-multiple"><div></div><div></div><div></div></div>';
    }
}
//インスタンス生成
const mo = new MutationObserver(addProgress);

//要素の監視を開始
mo.observe(targetElm, {childList: true});

監視対象はbodyタグで、DOMが変化したら(pace-progressが追加されたら)指定した関数を実行します。
もしpace-progressがあったらローティングアイコンの要素を追加します。

これで、ローディングアイコン用のタグを追加できました。

読み込み状況をパーセントで表示したい。

読み込み状況のパーセントは、PACEプラグインで生成されたpace-progressに記載されたデータ属性data-progress-textで取得できます。

<div class="pace-progress" data-progress-text="100%" data-progress="99" style="transform: translate3d(100%, 0px, 0px);">
    <div class="ball-scale-multiple">
        <div></div>
        <div></div>
        <div></div>
    </div>
</div>

疑似要素のcontentに属性値を設定することができます。読み込み状況のパーセントを表示するには次のように記載します。

content: attr(data-progress-text);

あとはCSSで表示位置を調整すれば完成です!

まとめ

PACEプラグインは読み込むだけで動作するので、簡単に動きのあるページを作成できます。
少しカスタマイズするだけで、オリジナルティあるローディングアイコンも設定可能なので機会があれば使おうと思います!