コンテンツを自動的に読み込んで無限スクロールさせる方法【jQuery連載13】
- カテゴリー jQuery活用サンプル
フォトギャラリーなどでページをスクロールして、次の写真を見る際などに、クリックで続きを見るなどもあるが、ここでは特定の枚数を読み込んでスクロールした際に次の読み込みたい内容を自動的に読み込む形を作成してみます。
こうすることによってクリックすることなくサイト全体の写真を見ることなども可能となります。
ウェブページを下にスクロールし続けていくと、ページを遷移せずに次に来るべきコンテンツを自動で読み込んで同じページに表示し続け、あたかも無限にスクロールし続けるような仕組みは一般的に「無限スクロール」と呼ばれ、Twitterをはじめ、SNSのFacebookやGoogle+、画像共有サービスのPinterestなど大手ウェブサービスで導入されている。
今回はこの「無限スクロール」の仕組みを、その手軽さから多くのサイトで導入されているInfinite Scrollプラグインで実装してみよう。
今回作成したサンプル
画像ではわかりにくいのでサンプルサイトをスクロールしてもらうと自動的に次の部分が読み込まれます。
【サンプル】コンテンツを次々に読み込んで無限にスクロールさせる
http://www.html5-memo.com/sample/jq-books/07/index.html
【サンプル】繰り返しループされた場合のサンプル
http://www.html5-memo.com/sample/jq-books/07/index_loop.html
無限スクロールを容易に実装できるInfinite Scrollプラグイン
無限スクロールの実装に使用するInfinite Scrollプラグインは多くのサイトで導入され、またブログ構築で人気のあるウェブアプリケーションWord Pressでも専用プラグインがあるなど、信頼性が高く、実績のあるjQueryプラグインだ。
今回のサンプルは「第10回 クリックでサイドから展開するスライドメニューを作成する」のサンプルをベースに無限スクロール機能を追加していくので、10で導入したスライドメニュー機能と、画像遅延読み込み機能のLazyloadプラグインについては詳しく触れないため、こちらを参照ください。
■第10回 クリックでサイドから展開するスライドメニューを作成する
http://www.html5-memo.com/jquery-tips/jquery10/
自動的に読み込むページの準備
無限スクロールの仕組みといっても特別難しいコーディングが必要な訳ではなく、そのページのコンテンツの最後に、次に見せたいページへのリンクを設定しておけば良い。
今回のサンプルではまず、1ページごとに5枚の写真を配置した複数のHTMLを用意し、最初に表示されるページを「index.html」とし、以後次々と見せたいページ(コンテンツ)を「page-2.html」「page-3.html」…と「page-」を接頭辞(プリフィックス)として連番でファイル名をつけておいた。
そして最初に表示するページ「index.html」のみ、ページ(コンテンツ)の終わり付近に特定のCSSセレクタをつけた要素とともに、次の表示させたいページのリンクを設置する。今回のサンプルではCSSセレクタ「navigation」のdiv要素内に、次のページにあたる「page-2.html」へのリンクを設定したa要素を配置した。
注意したいのが、この最初のページに設置したリンクのhref属性に設定したパス(ファイル名)が以後自動で読み込まれるファイル名の基準となることだ。具体的には、今回のサンプルのように次のページへのリンクを「page-2.html」とした場合は、2ページの最後で自動的に「page-3.html」が読み込まれ、それ以後も同様にファイル名の文字列の中の数字以前の文字を接頭辞とし、数字以後を拡張子などに設定して割り出されたファイル名を読み込もうと試みる。
このようなリンクは最初のページだけに設定すれば良く、他のページではリンクを設定する必要はない。2ページ目の「page-2.html」で仮に次へのリンクを「slide-1.html」としてもその設定は無視され、「page-3.html」を読み込もうとする。
<div id="galleryContainer" class="inner"> <div class="column"> <p class="photo shadow"> <img class="deferred" src="img/loader.gif" data-original="img/21.jpg" alt=""> <noscript><img src="img/21.jpg" alt=""></noscript> </p> </div> ・・・省略・・・ <div class="column"> <p class="photo shadow"> <img class="deferred" src="img/loader.gif" data-original="img/25.jpg" alt=""> <noscript><img src="img/25.jpg" alt=""></noscript> </p> </div> <div class="navigation"> <p><a href="page-2.html">Next</a></p> </div> </div>
Infinite Scrollプラグインの設定
HTMLの準備ができたら、次にJavascriptでInfinite Scrollプラグインを実行する設定を行う。無限にコンテンツを読み込む対象とした要素(今回のサンプルでは#galleryContainer)かinfinitescrollメソッドを実行するとともにその引数にオプションを設定する事で、読み込みタイミングや読み込み時の挙動などを細かく設定する事ができる。
今回はオプションに、Infinite Scrollプラグインの最低限の設定と、ページ読み込み後のコールバック関数を設定した。今回のサンプルでは無限スクロールの他、Lazyloadプラグインによる画像の遅延読み込み処理もおこなっているため、Infinite Scrollによって新しく読み込まれた画像要素に対して、画像遅延読み込み処理を実行している。このように新しく読み込まれた要素は元のページで設定した処理が反映されていない場合があるので、読み込み実行後のコールバックで実行するようにしておこう。
;(function (d, $) { var jQdm_slideMenu; jQdm_slideMenu = function(){ // 初期設定 var prop = { deferredImage: 'img.deferred', subContainer: '#subContainer', mainNavigation_trigger: '.mainNavigation_trigger', mainNavigation_appear: '.appeared', pagerContainer: '.navigation', pagerTargetContainer: '#galleryContainer', pagerLoadingContents: '#galleryContainer .column' } function init(){ // 画像の遅延読み込み関数を実行する deferredImage_setting() // スライドメニューの開閉ボタンの設定 $(prop.mainNavigation_trigger).find('a').on('click', function(){ $(prop.subContainer).toggleClass(replaceString(prop.mainNavigation_appear)); }); // 特定の要素までスクロールしたら、外部ページを読み込む $(prop.pagerTargetContainer).infinitescroll({ itemSelector: prop.pagerLoadingContents, animate: false, // ページ読み込み後に特定の位置までアニメーション移動させるか extraScrollPx: 300, // ページ読み込み後に移動する距離(px) pixelsFromNavToBottom: 50, // スクロール位置が、ページ下端からどれくらい距離で読み込みを開始するか(px) loading: { img: "img/loader.gif", // ローディング中の画像 msgText: "画像を読み込んでいます...", // ページ読み込み時に表示されるメッセージ finishedMsg: "すべて読み込まれました" // すべてのページが読み込まれた後のメッセージ }, }, function(_t, _opt){ // ページ読み込み後の処理 var _len = _t.length; while(_len--){ deferredImage_setting($(_t[_len]).find(prop.deferredImage)); } }); } …省略…
Infinite Scrollプラグインの読み込み先ファイルを自分で制御する
前述のようにInfinite Scrollプラグインは最初のページに設定したリンクのファイル名によって、それ以後はそのファイル名に則った連番ファイルが自動で読み込まれていく。ブログなどのウェブページを動的に生成するシステムでは、URI設定をカスタマイズしない限りは、大抵の場合、?page=1、?page=2…などの連番パラメータで紐付けられたURIで生成されるため、この仕組みで問題はないが、何かしらの理由で、読み込みの順序を自分で制御したいときは、Infinite Scrollのオプションを変更することで制御することが可能だ。
Infinite Scrollプラグインのオプションのつ「path」は、初期値は何も設定されていない(undefined)が、ここにパスの文字列を返す関数を設定しておけば、Infinite Scrollはその関数から返された文字列をファイル名として読み込みにいくようになる。2つめのサンプル(index_loop.html)は、Infinite Scrollプラグインのファイル読み込み先を自分で制御する記述を加えた「script_loop.js」を読み込んでいるため、4つ目のページ(page-4.html)の最後まで行った後、読み込み終了とはならずに再び最初のページ(index.html)を読みに行くようになり、延々とコンテンツが増えていくようになっている。
var prop = { …省略… page: { amoumt: 4, first: 'index.html', prefix: 'page-', extension: '.html' } } …省略… $(prop.pagerTargetContainer).infinitescroll({ …省略… path: (function(_num){ // 次に読み込むデータのパスを制御する関数 var _p = prop.page, _url = _num > _p.amoumt ? _p.first : _p.prefix + _num + _p.extension; return _url; }) } …省略… });
ページ遷移しないことのメリットとデメリット
「無限スクロール」などの仕組みで、シングルページ(単一ページ)で全てのコンテンツを見せることについては様々な意見があるとおもいます。
一般的な意見として、メリットはページ遷移をきっかけとしたサイト離脱を防ぐことができることや、モバイル環境において片手で次々とコンテンツを閲覧することができるシングルページが、ユーザーフレンドリーであることなどが挙げられる。逆にデメリットは、対策をしておかない限りは、ブラウザにページ履歴が残らないのでブラウザの「戻る」「進む」ことができないことや、目的の情報をすぐに探し出すことができない、PV(ページビュー)が減るなどが挙げられています。
導入の際は、サイトの特性にその仕組みが適しているかどうかを検討したり、A/Bテストなどをおこないながら、ユーザーにとって本当に使い勝手が良いかどうかを見極めていきましょう。
今回は以上になります。
次回はスクロール位置がボックス境界にスナップするページを作成します。
この記事を書いた人
著者 : ハヤシユタカ
2001年、有限会社ムーニーワークスを設立。WEB制作の他、書籍執筆、セミナー講演、企業研修などを行う。また、クリエイター育成機関デジタルハリウッドでは1999年より講師として本科WEBデザイナーコースやデジタルデザインコースを担当。 詳しいプロフィールはこちら