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
でイベント削除