Blog スタッフブログ

Pjax(非同期画面遷移)でシームレスな画面遷移ができるBarba.js

Category | Blog
/ 45,057views

こんにちは、Designer / EngineerからArt Directorに変わりました奥田です。
肩書きはあまり気にしていないのですが、Art Directorというと指示するだけでデザインしていないみたいなのと、後でTechnical Directorも付け加えるべきだなと思ったのは内緒です。

さて、最近ではページの読み込みにローディングをはさんでいるサイトがよくみられます。
そんな時、非同期でページ遷移すれば必要な箇所だけを読み込み、少ないロード時間でページをシームレスに変更することが出来ます。

そこで今回はPjax(非同期画面遷移)を導入できるBarba.jsをご紹介したいと思います。

Barba.js

サイトの中になぜPjaxを使うのか、そのメリットが掲載されていたのでご紹介します。

  • ページ間の素敵なトランジションを作成して、ユーザーのエクスペリエンスを向上させる可能性があります。
  • HTTP要求を減らす。(各ページの変更時にCSS / JSをリロードする必要がありますか?)
  • プリフェッチとキャッシュを使用してナビゲーションの高速化を可能にする。

それでは参りましょう。

Table of contents

  1. インストール
  2. 使い方
  3. イベント
  4. ヘッダーの取得
  5. 遷移時のアニメーション
  6. ページ毎に処理を変える方法
  7. 最後に

インストール

インストール方法はnpmを使ったインストール方法とScriptタグを使った方法どちらでも構いません。

npm install barba.js --save-dev
<script src="barba.min.js" type="text/javascript"></script>

Barba.jsは要素を以下のエレメントで囲う必要があります。

<div id="barba-wrapper">
  <div class="barba-container">
    ページごとのコンテンツ
  </div>
</div>

動作としては同一ドメインのリンク先の#barba-wrapper内の.barba-containerを取得し現在のページ内の.barba-containerと入れ替えるというものです。

使い方

使い方は以下です。
Barba.Pjax.start();を記述するだけで非同期遷移が可能になります。
headタグ内にscriptタグを記述している際はDOMContentLoadedイベントにバインドしてください。

import Barba from "barba.js"
module.exports = (function(){
    Barba.Pjax.start();
})();

また、Barba.jsにはプリフェッチという機能が標準でついており、リンクへマウスカーソルが乗った際や、スマホのtouchstartイベント時にリンク先を取得しに行く事ができます。プリフェッチを有効にすれば更に画面遷移を素早く行うことが出来ます。

Barba.Prefetch.init();

イベント

非同期に通信するとページロードなどのイベントが入り口のページにしか発生せず毎ページで何か実行したい際に上手く動かなくなってしまいます。
そんな時にBarba.jsが提供しているイベントにバインドすることでページ遷移時に処理を実行することが可能です。

Barba.Dispatcher.on(eventName, function() {
    // ここに処理を書きます。
});

イベントには以下の4つがあります。

イベント名実行のタイミング
linkClickedユーザーがPJAXのリンクをクリックした時。
initStateChangeリンクが変更された時。
newPageReady新しいコンテナがロードされ、ラッパーに挿入された時。
transitionCompleted移行が完了し、古いコンテナがDOMから削除された時。

ヘッダーの取得

Barba.jsではtitleタグの変更を行ってくれますがそれ以外のメタデータを変更してくれません。
ですのでページ遷移開始時にhead内の要素を取得し変更する処理を書いておくと便利です。

Barba.Dispatcher.on('newPageReady', function(currentStatus, oldStatus, container, newPageRawHTML) {
    var head = document.head;
    var newPageRawHead = newPageRawHTML.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0];
    var newPageHead = document.createElement('head');
    newPageHead.innerHTML = newPageRawHead;

    var removeHeadTags = [ 
        "meta[name='keywords']"
        ,"meta[name='description']"
        ,"meta[property^='og']"
        ,"meta[name^='twitter']"
        ,"meta[itemprop]"
        ,"link[itemprop]"
        ,"link[rel='prev']"
        ,"link[rel='next']"
        ,"link[rel='canonical']"
    ].join(',');
    var headTags = head.querySelectorAll(removeHeadTags)
    for(var i = 0; i < headTags.length; i++ ){
        head.removeChild(headTags[i]);
    }
    var newHeadTags = newPageHead.querySelectorAll(removeHeadTags)

    for(var i = 0; i < newHeadTags.length; i++ ){
        head.appendChild(newHeadTags[i]);
    }
});

遷移時のアニメーション

Pjaxといえばアニメーションでの画面遷移が表現できるということが制作者としては一番のメリットではないでしょうか。
Barba.jsではPromiseを使って読み込み完了とロードアウトを並列実行し、完了のタイミングを待ってからロードインを実行するように紹介されています。

var PageTransition = Barba.BaseTransition.extend({
    start: function() {
        // startはページトランジションの開始時に呼び出されるメソッド
        var _this = this;
        var _LoadOut =  new Promise(function(resolve) { 
            _this.LoadOut(resolve);
        });

        // トランジション開始と同時にnewContainerLoadingメソッドも呼ばれ、
        // トランジション用のメソッドとどちらもresolve()であればthen()が呼ばれる。
        Promise
            .all([this.newContainerLoading, this.loadOut()])
            .then(this.loadIn.bind(this));
    },
    loadOut :function(resolve){
        // 何かアニメーション処理を書いてその処理が完了した際にresolve()を実行する。
        resolve();
    },
    loadIn :function(){
        var _this = this;
        // 完了
        _this.done();
    },
});

最後にgetTransition内で実行することでトランジションが可能になります。

Barba.Pjax.getTransition = function() {
    return PageTransition;
};

アニメーションにはanime.jsがおすすめです。

anime.js

ページ毎に処理を変える方法

各ページ全てで同じ処理をさせるのではなく個別に何か処理を書きたい場合があります。
そんな時Viewという機能を使うと簡単に実装可能です。

まずは処理を書きたいページの.barba-containerにdata-namespaceを指定します。

<div class="barba-container" data-namespace="homepage">

次にBaseViewオブジェクトを継承することでそれぞれのイベント時に処理を実行できます。
最後にinit();を忘れずに。

var Homepage = Barba.BaseView.extend({
  namespace: 'homepage',
  onEnter: function() {
      // このページのcontainerが読み込みを開始した時。
  },
  onEnterCompleted: function() {
      // このページのトランジションが完了した時。
  },
  onLeave: function() {
      // 次のページへのトランジションが始まった時。
  },
  onLeaveCompleted: function() {
      // このページのcontainerが完全に削除された時。
  }
});

// 最後にinit()を実行することを忘れずに。
Homepage.init();

最後に

Barba.jsを入れただけでかっこいいサイトが作れるわけではないですが、アニメーションやエクスペリエンスの面だけでなくパフォーマンスのことも考慮し、Pjaxを導入すると更に一味違うサイトが作れます。
みなさんも是非参考にしてみてください。

Category | Blog
Author | Mineo Okuda / 45,057views

Company information

〒650-0024
神戸市中央区海岸通5 商船三井ビルディング4F

Contact us

WEBに関するお問い合わせは
078-977-8760 (10:00 - 18:00)