以下代码直接复制使用
<template>
<div style="height: 100%;">
<div style="display: flex;height: 100%;">
<div style="width: 200px;border: 1px solid pink;">
<div v-for="(item, index) in titleList" :key="index" style="margin-top: 10px;cursor: pointer;"
:style="{ backgroundColor: activeAnchor === item.dataKey ? 'cyan' : '#fff' }"
@click="() => scrollToAnchor(item.dataKey)">
{{ item.label }}
</div>
</div>
<!-- 这个大集合需要设置滚动 overflow: hidden;overflow-y: auto; -->
<div ref="scrollContainer" id="scrollContainer" style="flex: 1;overflow: hidden;overflow-y: auto;" @scroll="handleScroll">
<div ref="title1" id="title1" style="height: 200px; background-color: #c1f0de;">1</div>
<div ref="title2" id="title2" style="height: 600px; background-color: #c1f0de;margin-top: 10px;">2</div>
<div ref="title3" id="title3" style="height: 500px; background-color: #c1f0de;margin-top: 10px;">3</div>
<div ref="title4" id="title4" style="height: 200px; background-color: #c1f0de;margin-top: 10px;">4</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
activeAnchor: 'title1',//当前选中锚点
isScrollingToAnchor: false, //是否滚动中
titleList: [
{ dataKey: 'title1', label: '标题1' },
{ dataKey: 'title2', label: '标题2' },
{ dataKey: 'title3', label: '标题3' },
{ dataKey: 'title4', label: '标题4' },
]
}
},
methods: {
// 滚动监听 当前所展示的锚点
handleScroll() {
// 如果正在滚动到锚点,则不再触发新的滚动操作
if (this.isScrollingToAnchor) return false
const containerElement = document.getElementById('scrollContainer')
if (!containerElement) return
if (this.titleList && this.titleList.length) {
for (let i = 0; i < this.titleList.length; i++) {
const dataKey = this.titleList[i].dataKey
console.log('dataKey', dataKey, containerElement)
const anchorElement = document.getElementById(dataKey)
if (!anchorElement || anchorElement.length < 0) return
// getBoundingClientRect()方法返回一个DOMRect对象,该对象提供了元素的大小及其相对于视口的位置信息。这个DOMRect对象包含了元素的位置、宽度、高度和其他相关信息
const containerRect = containerElement.getBoundingClientRect()
// const anchorRect = anchorElement[0].getBoundingClientRect()
const anchorRect = anchorElement.getBoundingClientRect()
console.log(containerRect, anchorRect, dataKey)
// 判断锚点是否在滚动容器的可见区域内
const isInViewport =
anchorRect.top >= containerRect.top &&
anchorRect.bottom <= containerRect.bottom
if (isInViewport) {
this.activeAnchor = dataKey
return false
}
}
}
},
// 滚动锚点
scrollToAnchor(dataKey) {
const anchorElement = document.getElementById(dataKey)
// 使用原生JavaScript滚动到锚点位置
if (anchorElement) {
this.isScrollingToAnchor = true
anchorElement.scrollIntoView({
behavior: 'smooth', // 添加平滑滚动效果,可选
block: 'start' // 控制垂直方向的对齐方式,可选值有 'start', 'center', 'end', 'nearest'
})
this.activeAnchor = dataKey
// 滚动完成后将标志位复位
setTimeout(() => {
this.isScrollingToAnchor = false
}, 3000) // 3000 毫秒是滚动完成的估计时间,可以根据实际情况调整
}
}
},
}
</script>
<style></style>