前端项目里经常会有锚点得操作、以及反向联动的效果
就是一个菜单,点击会定位到一个块上,滚动的当前块的时候,菜单会出现定位的效果
差不多就是这种动起来的效果,由于不太懂之前的逻辑,今天又从重新看了下
上代码
html:
-----滚动的区域----------
<el-row class="panel-box part-detail" id="partdetail" :class="navClass">
--------菜单
<ul class="nav-list">
<li
:class="{ current: item.value === navCurrent }"
v-for="item in navList"
:key="item.value"
@click="linkTo(item.value)"
>{{item.label}}</li>
</ul>
---------------对应显示区域 注意id和class 后边要用
<h5 id="scene" class="do-jump">
应用场景
<p class="detail-content">{{ algorithmData.brief }}</p>
</h5>
<h5 id="word" class="do-jump">
使用文档
<ul
v-if="algorithmData.fileList && algorithmData.fileList.length > 0"
class="detail-content"
>
</h5>
<h5 id="explain" class="do-jump">
使用说明
<div class="detail-content">交付方式:{{ algorithmData.instruction.deliveryType }}</div>
</h5>
</el-row>
vuejs:
data() {
return {
imageLocalUrl,
navClass: '',
navList: [
{
value: 'scene',
label: '应用场景'
},
{
value: 'word',
label: '使用文档'
},
{
value: 'explain',
label: '使用说明'
}
],
navCurrent: 'scene',
typeMap: {},
algorithmData: {
instruction: {}
},
scrollBox: '',
scrollFalg: true
}
},
---------加入监听事件
mounted() {
window.addEventListener('scroll', this.scrollPage)
},
activated() {
window.addEventListener('scroll', this.scrollPage)
},
methods: {
------------锚点事件
linkTo(id) {
//点击时传值id
this.navCurrent = id
const el = document.querySelector(`#${id}`)
this.$nextTick(function() {
window.scrollTo({ 'behavior': 'smooth', 'top':el && el.offsetTop })
})
},
--------------反向联动
scrollPage() {
----------菜单控制样式
if (document.querySelector('#partdetail').getBoundingClientRect().top <= 0) {
this.navClass = 'fix-nav'
} else {
this.navClass = ''
}
/**
* 反向联动
*/
//获取所有锚点元素的高,并放在obj对象里 class用上了
const navContents = document.querySelectorAll('.do-jump')
const offsetTopArr = []
let temp = {}
for (let i = 0; i < navContents.length; i++) {
const e = navContents[i]
let temp = {
offsetTop: e.offsetTop,
id: e.id
}
offsetTopArr.push(temp)
}
// 获取当前文档流的滚动位置的高度 scrollTop
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
const domPosition = document.documentElement.scrollTop
//console.log("滚动时当前dom:"+domPosition)
// 定义当前点亮的导航下标
let navIndex = 'scene'
for (let n = 0; n < offsetTopArr.length; n++) {
// 如果 scrollTop 大于等于第 n 个元素的 offsetTop 则说明 n-1 的内容已经完全不可见
// 那么此时导航索引就应该是 n 了
if (scrollTop >= offsetTopArr[n].offsetTop) {
navIndex = offsetTopArr[n].id
}
}
this.navCurrent = navIndex
console.log('滚动到的菜单:' + this.navCurrent)
//this.linkTo(navIndex)
console.log('navIndex:' + navIndex + '########')
}
},
},
deactivated() {
window.removeEventListener('scroll', this.scrollPage)
},
destroyed() {
window.removeEventListener('scroll', this.scrollPage)
}
css:
.part-detail {
margin-top: 15px;
padding: 0;
.nav-list {
display: flex;
border-bottom: 1px solid #ededed;
font-size: 16px;
margin: 0;
li {
padding: 16px 0;
margin: 0 16px;
cursor: pointer;
&:first-child {
margin-left: 46px;
}
&.current {
color: #ff6400;
border-bottom: 3px solid #ff6400;
}
}
}
&.fix-nav {
padding-top: 54px;
//color: red;
.nav-list {
position: fixed;
background: #fff;
top: 0;
float: right;
z-index: 5;
left: 140px;
right: 140px;
}
}
}
代码已基本如此
思路:
每一个区域加上相同的calss,滚动的时候获取距离,
得到菜单对应的下标(id)和距离上部元素的高度,便于滚动
得到当前滚动的高度和内容块的距离做比较,大于则菜单变动,出现效果
后记:前端刚上手,还有很多不会的,借助修改bug的机会能学到更多,这个本来的效果时这种实现的
// 锚点跳转
// linkTo(id) {
// this.navCurrent = id
// this.scrollFalg=false
// console.log('当前点击的菜单:' + this.navCurrent)
// // 要移动的距离登录本身减去nav-list底部位置
// const jump = document.querySelector(`#${id}`).getBoundingClientRect().top - document.querySelector('.nav-list').offsetHeight
// // 获取当前dom位置
// const domPosition = document.documentElement.scrollTop
// //console.log("点击时当前dom:"+domPosition)
// let index = 0
// let moveTime = null
// clearInterval(moveTime)
// moveTime = setInterval(() => {
// if (++index === 50) {
// clearInterval(moveTime)
// return
// }
// // 每次移动1/50,50次移动完毕
// document.documentElement.scrollTop = domPosition + (jump / 50) * index
// }, 10)
// //this.scrollFalg=true
// },
这样很好,直接锚点跳到当前内容顶部,效果很好,但是在监听滚动的时候,反向联动和点击事件或冲突,无奈修改了,定位不如之前的准,到那时反向的效果有了,也希望有人看到后指教一下