LoginSignup
50
59

More than 5 years have passed since last update.

【Barba.js版】高速かつスムーズなページ遷移を実現する pjax 覚書

Last updated at Posted at 2018-04-13

2年くらい前に書いた「高速かつスムーズなページ遷移を実現する pjax 覚書」に直近でも「いいね!」が付くので、もうちょっとイマドキな実装方法に書き直してみようと思います。

今回ご紹介するライブラリは「Barba.js」というもので、「Pjax」を簡単に実装できるライブラリの一つになります。

Barba.js 公式サイト

こういった感じのサイトが作れます。

Circles Demo

アイディア次第では、面白い見せ方ができそうですね。

これからWebサイトにシームレスなページ遷移演出を実装したいと考えている方は是非参考にしてみてください。

演出実装の基本

この「Barba.js」を導入することで、「Ajax+PushState」という基本的なPjaxの機能が実装できるほか、APIが充実しており「リンクのクリック直後」や「ページの読み込み前」、「ページの読み込み完了後」などの状態を簡単に取得できるようになります。
この状態に応じてJSでクラス追加/削除処理を書き、CSSでアニメーションさせるのがベターな実装方法かなと思います。

導入方法

詳しくは公式サイトに書かれているとおりですので、ざっくりと説明します。

Barba.js - Installation

インストールはnpmやCDNなどを使いましょう。
もちろん普通にダウンロードしても動きます。

npm install barba.js --save-dev
<script src="https://cdnjs.cloudflare.com/ajax/libs/barba.js/1.0.0/barba.min.js"></script>

非同期で読み込ませたい親要素に id="barba-wrapper" を付与し、その直下の子要素に class="barba-container" を付与します。
※Pjaxが適用されるすべてのページに記述します。

<div id="barba-wrapper">
  <div class="barba-container">
    <!-- ここに非同期で読み込ませたい内容を記述 -->
  </div>
</div>

あとはJS側でBarba.jsを実行すれば導入完了です。

Barba.Pjax.start();

イベントを取得してみる

Barba.jsには以下のようなイベントが存在します。

イベント名 引数 発火タイミング
linkClicked HTMLElement, MouseEvent ユーザーがpjaxが設定されたリンクをクリックしたとき
initStateChange currentStatus リンクが変更されたとき
newPageReady currentStatus, prevStatus, HTMLElementContainer, newPageRawHTML 新しい要素が読み込まれ、コンテナ要素に挿入されたとき
transitionCompleted currentStatus[, prevStatus] 遷移処理が完了し、以前の要素が削除されたとき

これらのイベントをリスナに登録するには、以下のBarba.js専用のメソッドを利用します。

Barba.Dispatcher.on('イベント名', () => {
  // ここに処理を書く
});

例えば次の例では、「リンクをクリックしたときに bodyis-transition-start クラスを追加する」という処理になります。

Barba.Dispatcher.on('linkClicked', (HTMLElement, MouseEvent) => {
  document.body.classList.add('is-transition-start');
});

ページごとに処理を変えたい場合

例えばmetaタグの動的変更など、ページごとに個別でJSを発火させたい場合は、newPageReady イベントで取得できる引数 currentStatus 内の namespace 値を取得して条件分岐させる方法があります。

namespace は、各ページの barba-container クラスに data-namespace="任意の名前空間" として記述しておくことで利用できるようになります。

TOPページだけ任意のJSを実行したいときは、下記のように書きます。

<div class="barba-container" data-namespace="top">
Barba.Dispatcher.on('newPageReady', (currentStatus, oldStatus, container) => {
    switch (currentStatus.namespace) {
    case 'top':
        // data-namespace="top"のときに実行させたい処理
        console.log('topで実行されました');
        break;
    ...
});

この方法でもよいのですが、Barba.jsのヘルパー機能として提供されている「Views」を使うともっと効率的に書くことが可能です。

Barba.js - Views

上記と同じ処理をViewsで書くと...

const Top = Barba.BaseView.extend({
    namespace: 'top',
    onEnterCompleted: () => {
        // 準備されたコンテナへの遷移が完了したときに実行される
        console.log('topで実行されました');
    },
});

Top.init();

簡潔に書くことができました。
上記はTOPページのみの処理ですが、他のページ分も同様に関数を追加していけば良いです。

また、onEnter, onEnterCompleted, onLeave, onLeaveCompleted など遷移状態に応じて処理を分岐させることも可能です。

遷移アニメーションをつけたデモ

下記ページにて用意しました。

今まで紹介したイベントやViewsなどを使っています。
また、軽い遷移アニメーションもつけてみました。

linkClicked イベントと transitionCompleted イベントを利用し、クラスを追加/削除しているだけです。
あとはCSSアニメーションの作り込み次第で超イケてるサイトが作れるかと思います!

ソースコードはこちら

リンクをクリックしたときにPjax遷移をさせたくない場合

デフォルトだと target="_blank" を除くすべてのリンクにPjaxイベントが適用されてしまいます。

遷移させたくないリンクに関しては、no-barba クラスをaタグに付与すれば良いです。

Barba.Pjax.preventCheck メソッドを拡張することでも対応できるっぽいです。
詳しくはこちらのページに書かれていますのでチェックしてみてください。

Is it possible to ignore barba.js on some links?

あとがき

SPAなどが流行ってPjaxは古い技術...と思われがちですが、導入コストの低さからWebサイト制作界隈においてはまだまだ使える技術だと思っています。

Webサイトに一工夫したいときや体感速度を向上させたいときなどに是非導入をご検討ください。

50
59
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
59