Nuxt.js(Vue.js)でScroll Indicatorを作る

コンポーネント

ScrollIndicator.vueを作る。

<template>
  <div
    class="v-scroll--indicator-wrapper"
    :style="{ height: height, background: background }"
  >
    <div
      class="v-scroll--indicator"
      :style="{ background: color, width: width }"
    />
  </div>
</template>

<script>
export default {
  name: "ScrollIndicator",

  props: {
    height: {
      type: String,
      default: "5px",
      required: false,
    },
    color: {
      type: String,
      default: "linear-gradient(to right, #FEE645, #FEE645)",
      required: false,
    },
    background: {
      type: String,
      default: "#F9FAFB",
      required: false,
    },
  },

  data() {
    return {
      scrolled: "",
      docHeight: "",
      width: "",
    }
  },
  mounted() {
    window.addEventListener("load", this.scrollHandler)
    window.addEventListener("scroll", this.scrollHandler)
  },
  destroyed() {
    window.removeEventListener("load", this.scrollHandler)
    window.removeEventListener("scroll", this.scrollHandler)
  },
  methods: {
    scrollHandler() {
      let article = document.getElementById("article")
      if (article) {
        let articleHeight = article.scrollHeight
        this.scrolled =
          document.body.scrollTop || document.documentElement.scrollTop
        this.docHeight = articleHeight - document.documentElement.clientHeight
        this.width = (this.scrolled / this.docHeight) * 100 + "%"
      }
    },
  },
}
</script>
<style scoped>
.v-scroll--indicator-wrapper {
  /* position: fixed; */
  top: 0;
  right: 0;
  left: 0;
  z-index: 9999;
  width: 100%;
  margin-top: 0.5rem;
}
.v-scroll--indicator {
  width: 0;
  height: 100%;
}
</style>

使い方

記事のページのid="article"を見て判断する。

<div id="article">
  ...記事
</div>

Headerの下に入れる。

<ScrollIndicator />

モバイルでは表示しない && 記事ページ以外では表示しない場合、

<ScrollIndicator v-show="$route.name === 'slug' && $device.isDesktop" />

SSRだと、v-ifでも行けるみたい。

ポイント

  • mountedを使用する。createdでは、windowプロパティが読み込めない。
  • articleHeightは、記事の長さ
  • document.documentElement.scrollTopは、スクロールした長さ
  • document.documentElement.scrollHeightは、スクロールできる長さ
  • document.documentElement.clientHeightは、heightとpaddingの合計から、スクロールバーの幅を引いた高さ(borderは含まない)
  • window.addEventListenerでイベント登録
  • window.removeEventListenerでイベント削除

資料