vue项目中实现锚点定位
使用场景:当页面被分割成许多小模块,且页面很长时,锚点功能可以帮助我们快速跳转到想要的模块;而当滑动滚动条时,根据当前视图中的显示的模块自动选中对应的锚点。
·
使用场景:当页面被分割成许多小模块,且页面很长时,锚点功能可以帮助我们快速跳转到想要的模块;而当滑动滚动条时,根据当前视图中的显示的模块自动选中对应的锚点。
思路
锚点的id对应模块的元素的id。点击锚点时,根据id找到对应的模块,获取此模块距离父级元素的顶部的距离,然后控制父级的滚动条scrollTo到此距离。
到此只实现了一半,即点击锚点页面滚动到对应的模块内。还需要实现锚点跟随滚动条的位置自动选中。
实现另一半需要监听滚动事件,在滚动事件中遍历锚点列表,根据锚点id获取对应的模块元素,计算当前滚动条位置处于哪个模块的位置内,从而将此锚点设为选中状态。
代码
html
<template>
<div class="info-body">
<!--锚点列表-->
<ul class="archor">
<li :class="activeStep === anchor.id ? 'active' : ''"
v-for="(anchor, index) in anchorList"
:key="index" @click="jump(anchor.id)">
<span>{{ anchor.name }}</span>
</li>
</ul>
<!--隐藏滚动条-->
<div class="hid-scroll-bar">
<div class="scroll-box" id="scroll-box">
<!--模块列表-->
<div v-for="(item, index) in modules"
class="info-panel"
:key="index"
:id="item.id">
<div class="info-content">
<!--模块内容-->
</div>
</div>
</div>
</div>
</div>
</template>
js
data() {
return {
activeStep: '',// 默认选中的锚点的key值
offsetTop: 0,
}
},
computed: {
scrollFn() { // 防抖
return _.debounce(
this.scroll, 100
)
},
anchorList() { // 锚点列表
return [
{ id: 'anchor1', name: '锚点1' },
{ id: 'anchor2', name: '锚点2' },
{ id: 'anchor3', name: '锚点3' },
];
},
modules() { // 模块列表
return [
{ id: 'anchor1', title: '模块1' },
{ id: 'anchor2', title: '模块2' },
{ id: 'anchor3', title: '模块3' },
];
},
},
mounted() {
window.addEventListener('scroll', this.scrollFn, true)
},
beforeDestroy() {
window.removeEventListener('scroll', this.scrollFn, false)
},
methods: {
scroll() {
const box = document.getElementById('scroll-box')
// 若当前设置的滚动高度大于实际滚动的高度,即为锚点跳转,不再设置选中的锚点
if(this.offsetTop > box.scrollTop) {
this.offsetTop = 0
return
}
let totalH = 0
this.anchorList.some(anchor=> {
let scrollItem = document.getElementById(anchor.id)// 锚点对应的模块
totalH = totalH + scrollItem.clientHeight
let judge = box.scrollTop < totalH
if(judge) {
this.activeStep = anchor.id
return true
}
})
},
jump(id) {
this.activeStep = id // 设置选中的锚点为当前点击的
const box = document.getElementById('scroll-box')
let scrollItem = document.getElementById(id)
// 锚点对应的模块与最近的一个具有定位的祖宗元素顶部的距离
this.offsetTop = scrollItem.offsetTop
box.scrollTo({
top: scrollItem.offsetTop,
behavior: "smooth",
});
},
}
css
/*锚点*/
.archor {
position: absolute;
right: 16px;
display: flex;
flex-direction: column;
width: 40px;
list-style: none;
li {
height: 80px;
border-right: 3px solid #FAFAFA;
display: flex;
flex-direction: column;
justify-content: center;
cursor: pointer;
&:first-child {
justify-content: flex-start;
}
&:last-child {
justify-content: flex-end;
}
&.active {
border-color: $primary-color;
}
}
}
.info-body {
position: relative;
width: 65%;
border-left: 2px solid #F2F2F2;
padding: 2px 82px 0 0;
box-sizing: border-box;
}
/*双重包裹,隐藏滚动条*/
.hid-scroll-bar {
position: relative;
width: 100%;
height: 100%;
.scroll-box {
height: 100%;
width: 100%;
overflow-y: auto;
position: absolute;
&::-webkit-scrollbar {
display: none;
}
}
}
效果
相关连接
更多推荐
已为社区贡献1条内容
所有评论(0)