Help us understand the problem. What is going on with this article?

Barba.js(v2)を使ってネイティブ風な動きを実装する

非SPAのサイトでネイティブ風な動きを実装したいと思い、Barba.jsを使ったので、その時に対応したことなどメモ。

完成したもの

gifなので、速度は結構早いですが、、、

barba動き.gif

行った手順

Barba.jsのインストール

$ npm i @barba/core 

参考 : https://barba.js.org/docs/v2/user/index.html

polyfill対応

IEにもBarba.jsを対応させる場合、polyfillが必要となるので、

<script
  crossorigin="anonymous"
  src="https://polyfill.io/v3/polyfill.min.js?features=default%2CArray.prototype.find%2CIntersectionObserver"
></script>

を追記する。

参考 : https://barba.js.org/docs/v2/user/index.html#browser-support

基本的な遷移まで

import barba from '@barba/core'
barba.init()
<div data-barba='wrapper'>
  <!-- headerなど -->
  <div data-barba='container' data-barba-namespace='pageName'>
    <!-- ここに変更するコンテンツを配置する -->
  </div>
  <!-- footerなど -->
</div>

参考 : https://barba.js.org/docs/v2/user/core.html

ページ遷移時に簡単なアニメーションを実装する

https://liginc.co.jp/476913 のコード参考

$ npm i @barba/css
import barba from '@barba/core'
import barbaCss from '@barba/css' // 追記

barba.use(barbaCss) // 追記
barba.init()
.barba-leave-active,
.barba-enter-active {
    transition: opacity 0.4s ease;
}

.barba-leave {
    opacity: 1;
}

.barba-enter {
    opacity: 0;
}

.barba-leave-to {
    opacity: 0;
}

.barba-enter-to {
    opacity: 1;
}

公式 : https://barba.js.org/docs/v2/user/css.html

prefetch導入

$ npm i @barba/prefetch
import barba from '@barba/core'
import barbaCss from '@barba/css'
import barbaPrefetch from '@barba/prefetch' // 追記

barba.use(barbaCss)
barba.use(barbaPrefetch) // 追記
barba.init()

参考 : https://barba.js.org/docs/v2/user/prefetch.html

polyfill追記

自分の環境だと公式のpolyfillだけではエラーになったため、以下のコードで対応。(既存のものからNodeList.prototype.forEachを追加しただけです。)

<script crossorigin='anonymous' src='https://polyfill.io/v3/polyfill.min.js?features=default%2CArray.prototype.find%2CIntersectionObserver%2CNodeList.prototype.forEach'></script>

polyfillについては https://polyfill.io/v3/url-builder/ を参考。

同じurlの場合、ページ遷移をさせない

同じリンク上だとページの読み込みが行われてしまうため。

参考 : https://gist.github.com/mhige/a5fe953de730afdd353e2432ace909b0#file-barba-custom-js-L3-L12

import barba from '@barba/core'
import barbaCss from '@barba/css'
import barbaPrefetch from '@barba/prefetch'

barba.use(barbaCss)
barba.use(barbaPrefetch)
barba.init()

// ここから追記

const eventDelete = e => {
  if (e.currentTarget.href === window.location.href) {
    e.preventDefault()
    e.stopPropagation()
    return
  }
}

const links = [...document.querySelectorAll('a[href]')]
links.forEach(link => {
  link.addEventListener('click', e => {
    eventDelete(e)
  }, false)
})

titleタグ以外のmetaタグの情報の書き換えを行う

公式のままだとtitleタグは変更させますが、descriptionタグなどについては更新されないため。

参考 : https://gist.github.com/mhige/a5fe953de730afdd353e2432ace909b0#file-barba-custom-js-L22-L45

barba.init以外は変更していないため省略。

// 省略(barba.use(barbaPrefetch)より上)

const replaceHeadTags = target => {
  const head = document.head
  const targetHead = target.html.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0]
  const newPageHead = document.createElement('head')
  newPageHead.innerHTML = targetHead
  const removeHeadTags = [
    "meta[name='keywords']",
    "meta[name='description']",
    "meta[property^='fb']",
    "meta[property^='og']",
    "meta[name^='twitter']",
    "meta[name='robots']",
    'meta[itemprop]',
    'link[itemprop]',
    "link[rel='prev']",
    "link[rel='next']",
    "link[rel='canonical']",
  ].join(',')
  const headTags = [...head.querySelectorAll(removeHeadTags)]
  headTags.forEach(item => {
    head.removeChild(item)
  })
  const newHeadTags = [...newPageHead.querySelectorAll(removeHeadTags)]
  newHeadTags.forEach(item => {
    head.appendChild(item)
  })
}

barba.init({
  transitions: [
    {
      beforeEnter({ next }) {
        replaceHeadTags(next)
      }
    }
  ]
})
//省略(const eventDelete = e => {より下)

transitionのオプションについて

名前 説明
before 最初
beforeLeave 現在のページを離れる直前
leave 現在のページを離れる時
afterLeave 現在のページを離れた直後
beforeEnter 次のページを表示する直前
enter 次のページを表示する時
afterEnter 次のページが表示された直後
after 最後

その他オプションについては https://barba.js.org/docs/v2/user/core.html#hooks 参考。

ページ遷移時にGoogle Analyticsに情報を送信

参考 : https://gist.github.com/mhige/a5fe953de730afdd353e2432ace909b0#file-barba-custom-js-L47-L48

// いろいろ省略
const gaPush = pagename => {
  ga('send', 'pageview', pagename)
}
barba.init({
  transitions: [
    {
      beforeEnter({ next }) {
        // replaceHeadTags(next)の処理
        gaPush(location.pathname)
      }
    }
  ]
})

ページ遷移時にページの一番上まで行く。

ページをスクロール → リンククリック → ページ遷移だとスクロールの値が保存されていたので、それを0にする。

// いろいろ省略
barba.init({
  transitions: [
    {
      beforeEnter({ next }) {
        // gaPush(location.pathname)の処理
        const scrollElem = document.scrollingElement || document.documentElement
        scrollElem.scrollTop = 0
      }
    }
  ]
})

Barbaの範囲外も適応させたい

現状だと headerfooterなどは一切動かないため動きを追加する。(簡単なクラスの付け替えなど)

barba.init({
  transitions: [
    beforeEnter({ next }) {
      const header = document.querySelector('.l-header') // header要素取得
      header.classList.toggle('is-active') // クラスの付け替え
      // その他いろいろ
    }
  ]
})

参考リンク一覧

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away