实现效果如图:
实现原理:
1. 将原右侧导航栏样式在全局css中改为常显示以及宽度为零。
body {
background-color: #3c3c3c;
overflow-x: hidden;
overflow-y: scroll;
}
::-webkit-scrollbar {
width: 0;
}
2. 在后缀为.vue
的文件中或者在自定义的布局(nuxt中的layouts)中,加入这两个id
<template>
<div>
<!-- 导航栏上层样式 -->
<div id="progressbar"></div>
<!-- 导航栏底层背景 -->
<div id="scrollPath"></div>
</div>
</template>
3.在全局样式common.css
中引入自定义导航栏的样式
/* 导航栏背景 */
#scrollPath {
position: fixed;
top: 0;
right: 0;
width: 10px;
height: 100%;
background-color: rgba(255, 255, 255, 0.068);
}
/* 导航栏样式 */
#progressbar {
position: fixed;
top: 0;
right: 0;
width: 10px;
/* height: 100%; */
background: linear-gradient(to top, red, blue);
animation: animate 5s linear infinite;
}
@keyframes animate {
0%, 100% {
filter: hue-rotate(0deg);
}
50% {
filter: hue-rotate(360deg);
}
}
#progressbar::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to top, red, blue);
filter: blur(10px);
}
#progressbar::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to top, red, blue);
filter: blur(30px);
}
4.核心:用户获取划过的距离 除以
( 页面内容总高度 减去
文档显示区高度 ),进行计算要显示导航栏占整个页面的百分比,替换高度,从而进行显示。
!!!坑:因为Vue中存在Dom渲染完成之后渲染数据,因此,在mounted()中执行导航栏计算方法,只能得到请求的页面数据未渲染之前的初始的高度,数据渲染之后和这里的高度不对应!
!!!解决方案:使用watch
监听要渲染的数据,使用this.$nextTick(() => {});
属性将回调延迟到下次 DOM 更新循环之后执行。
因为每个页面渲染的数据都不同,所以在每个后缀为.vue
的页面中都要watch监听要渲染的数据。如果没有请求的页面数据,那直接将function中的内容放入mounted()中即可。
watch: {
"data": function() {
this.$nextTick(() => {
let progress = document.getElementById("progressbar");
//innerheight 返回窗口的文档显示区的高度。
//document.documentElement.scrollHeight——浏览器所有内容高度
//window.pageYOffset 划过的距离
let totalHeight = document.body.scrollHeight - window.innerHeight;
window.onscroll = function() {
let progressHeight = (window.pageYOffset / totalHeight) * 100;
progress.style.height = progressHeight + "%";
};
});
}
},