MENU

Journal

3 : ページ遷移後の処理
画像のロードを待つための処理
→ imagesLoadedというJSライブラリを使用
→ 画像の読み込みを完了後にローディングを隠す処理を実行

ブラウザバックした時にローディング画面が出っぱなしになってしまう
→ window.onpageshow〜 を使用してブラウザバックを検知してローディング画面を隠す

全3回でご紹介の、「ajaxっぽい画面遷移」
少し時間が空いてしまいましたが今回が完結編となります。
第2回は実践編として
リンクの通常の挙動をストップ→ローディングを表示→ページ遷移という
前半の処理の基本的な流れを説明しました。

実践編の後半の今回は、

  1. 「imagesLoaded」を使って簡単にプログレスバーのあるローディング画面を実装する
  2. window.onpageshowを使用し、ブラウザバックを検知してローディング画面を隠す

という流れで説明したいと思います。

1. 「imagesLoaded」を使って簡単にプログレスバーのあるローディング画面を実装する

前回の処理で無事、同じ見た目の画面へのページ遷移をし
「ajaxっぽい画面遷移」の前半部分ができましたが、
この後、画像の表示されていない状態でロード画面が開けてしまっては
格好がつかないので、画像のロードを待ってから
ロード画面を開けるという処理を行いたいと思います。

イメージのロード完了を手動で検知させるということもできますが、
ここでは便利なライブラリの「imagesLoaded」を使いたいと思います。

使い方は簡単で、
公式ページから、ダウンロードするか、CDNでjsファイルを読み込んで使います。
jQueryを使用する場合は
$('#container').imagesLoaded( function() { /* 画像読み込み後の処理 */ });の形で、
指定の要素に含まれる画像を読み込んだあとにさせたい処理を書くだけです。
画像のローディングに対して簡単なプログレスバーも実装したいので、
imagesLoadedのprogressというメソッドも使ってみたいと思います。

    <div id="loading"><span>LOADING</span><div id="bar"></div></div>
    
    #loading {
      background-color: #f0f0f0;
      position: fixed;
      top: 0%;
      left: 0;
      width: 100%;
      height: 100%;
      z-index: 10000;
      transition: ease .5s;
    }
    #loading.is-hidden {
      opacity: 0;
      top: -100%;
    }
    #loading span {
      font-family: sans-serif;
      display: block;
      text-align: center;
      width: 100%;
      height: 40px;
      color: #ccc;
      font-size: 16px;
      letter-spacing: 4px;
      text-indent: -4px;
      position: absolute;
      top: calc( 50% - 10px );
      left: 0;
    }

    /* ローディング画面の下端にプログレスバーを表示 */
    #loading #bar {
      position: absolute;
      display:block;
      height: 6px;
      width: 0%;
      bottom: 0;
      left: 0;
      background-color: rgba(255, 96, 96, 1);
      transition: ease .1s;
    }
    #loading #bar.hide {
      opacity: 0;
    }
    
      $(function(){
        var loading = $('#loading');
        var links = $('a.movepage');
        var bar = $('#bar');

        links.on('click',function(event){
          // クリック時に発生するイベントをキャンセル
          event.preventDefault();

          // ローディング画面を表示
          loading.removeClass('is-hidden');

          // 移動先のURLを取得して指定秒数後にページ遷移する
          var href = $(this).attr('href'), // クリックしたリンクから遷移先URLを取得
              wait = 500; // 待ち時間をミリ秒で指定
          setTimeout(function(){
            // ページ遷移の処理
            location.href = href ;
          }, wait);
        });

        // #content内の画像のロード時に下の関数を実行
        $('#content').imagesLoaded()
          .progress( advanceLoading )
          .done( hideLoading );

        function advanceLoading(e){
          // プログレスバーを進める
          var length = e.images.length, // 画像の枚数
              count = e.progressedCount, // 読み込み完了した枚数
              progress =  ( count / length ) * 100; // パーセントの値に

          bar.width( progress + '%' );

          if( progress == 100 ){
            // 100%になったらバーを隠す
            bar.addClass('is-hidden');
          }
        }

        function hideLoading(){
          // ローディング完了のタイミングでローディング画面を隠す
          loading.addClass('is-hidden');
        }

      });
    

上記では、画像の枚数に対してローディング完了した枚数を
imagesLoadedのメソッドから取得し、
それを%に直して#barのwidthを変更して
プログレスバーを実装しています。

また、ローディング完了時に実行されるdoneメソッドを使って、
ローディング完了時にローディング画面を隠すための処理(クラスをつけるだけですが)
を実行しています。

2. window.onpageshowを使用し、ブラウザバックを検知してローディング画面を隠す

さて、これでajaxっぽい動きを実装するための一通りの処理はできたのですが、
safari等で表示したとき、このままブラウザバックをすると、
ローディング画面が出た状態の画面に遷移してしまいます、
これはブラウザの仕様でブラウザバックをすると、
キャッシュしてあるページを読みに行ってリロードしないために起こる現象のようで、
※bfcache( Back-Forward Cache ) というらしいです。
通常の場合はこのお陰でブラウジングが快適になるようなのですが、
今回の処理ではこの機能のお陰でページが見えない状態になってしまいます。

そこで、pageshowというイベントと、
初回ロード時にはfalseがセットされるpersistedというプロパティを
利用して下記の処理を追加し、
ブラウザバックで戻った場合にはローディング画面を隠す処理をさせます。

      $(function(){
        var loading = $('#loading');
        var links = $('a.movepage');
        var bar = $('#bar');

        links.on('click',function(event){
          // クリック時に発生するイベントをキャンセル
          event.preventDefault();

          // ローディング画面を表示
          loading.removeClass('is-hidden');

          // 移動先のURLを取得して指定秒数後にページ遷移する
          var href = $(this).attr('href'), // クリックしたリンクから遷移先URLを取得
              wait = 500; // 待ち時間をミリ秒で指定
          setTimeout(function(){
            // ページ遷移の処理
            location.href = href ;
          }, wait);
        });

        // #content内の画像のロードのに対して下の関数を実行
        $('#content').imagesLoaded()
        .progress( advanceLoading )
        .done( hideLoading )

        function advanceLoading(e){
          // プログレスバーを進める
          var length = e.images.length, // 画像の枚数
              count = e.progressedCount, // 読み込み完了した枚数
              progress =  ( count / length ) * 100; // パーセントの値に

          bar.width( progress + '%' );

          if( progress == 100 ){
            // 100%になったらバーを隠す
            bar.addClass('is-hidden');
          }
        }

        function hideLoading(){
          // ローディング完了のタイミングでローディング画面を隠す
          loading.addClass('is-hidden');
        }

        // ブラウザバック時のローディング画面対策
        window.onpageshow = function(e) {
          if( e.persisted == true ){
            // ローディング画面を隠す
            hideLoading();

            /* もしローディング画面を出す以外にも画面遷移時に処理を行っている場合など、
             * 何らかの不具合が出た場合には、
             * 画面を読み込み直すのでブラウジングのスムーズさが少し損なわれてしまいますが、
             * 強制的にリロードさせる下記の処理をさせると大体解決します。*/
            // window.location.reload();
          }
        }
      });
    

全3回に渡って書いてきました、
「ajaxっぽい画面遷移」の実装方法もこれでおしまいです。
もし「リッチなWEBサイトを作りたいけど、あまり工数がかけられない!」という
フロントエンドの皆さまのお役に立てば幸いです!

それでは、今年はこれでブログ納となりますが、
来年もどうぞよろしくお願いいたします。
皆さま良いお年を!

Journal

CLOSE