一个人的时候,怎么过?就算再难以承受,其实到最后我们总能走得过来。
前言
前两天面试的时候,面试官要求附上一个测试作品,给了一个网站(coding.qq.com/home/ ,没错就是这个网站) 让我复刻其中的交互效果,其中就有一块涉及到了锚点定位。因为我之前也没做过这类功能,就觉得挺好玩的,然后也顺手记录一下,要是能帮到某些同学,那就再好不过了~
正文
tip: 这个demo用的是vue3加pinia搭建的,有兴趣的同学,demo源码放在这里哦[~]
第一步 定锚点
给需要定位的组件加上id,后面查找元素需要用到哦(划重点)
<template>
<div class="main-container w" id="main">
<!-- 通知栏 -->
<Notice />
<!-- 赛事活动专区 -->
<Activity />
<!-- 编程好工具 -->
<CodingTool id="labs" />
<!-- 趣味课程,名师名家带你学 -->
<Interesting id="courses" />
<!-- 精彩作品,学以致用 -->
<Production id="project" />
<!-- 扣叮动态 -->
<News id="codingnews" />
<!-- 校园风采 -->
<School id="cocase" />
<!-- 合作伙伴 -->
<Partner id="cooperator" />
</div>
</template>
第二步 通过导航栏让锚点动起来!
其实这一步,就是先通过导航栏的点击事件和锚点进行联动,导航栏也就是下面这个东东
这一步的关键点有以下两个
1. 先使用element.scrollTo方法(使界面滚动到给定元素的指定坐标位置)定义一个锚点定位滚动方法
为了使界面滚动到给定元素(也就是锚点)的指定坐标位置,这里我们用到了这个srollTo这个方法,怎么使用呢,我从mdn截图下来了,可以参考参考,使用方法灰常简单
我代码里用的options的参数形式,具体代码如下: 这个方法里需要注意的点:
parent取的是锚点定位元素的可滚动父级元素,这里我拿的是最外层,id为app的元素,大家可以根据实际情况取不同的可滚动父级元素
scrollTo(offsetTop) {
const parent = document.querySelector('#app')
parent.scrollTo({
top: offsetTop,
behavior: 'smooth'
})
}
2. 获取锚点的offsetTop(距离父级元素的顶部距离)
上面我们已经定义好了锚点定位的滚动方法,只要向里面传入一个参数(锚点距离父元素的顶部距离offsetTop)就可以愉快地滚动啦。
获取锚点的offsetTop比较简单,使用document.querySelector拿到对应锚点的元素,再取其中offsetTop的属性值就行啦,代码如下:
anchorPosition(anchor) {
const element = document.querySelector(anchor)
this.scrollTo(element.offsetTop)
}
这样导航栏跟锚点点击联动的基本工具就搞定了,这一步是不是灰常简单
接下来就是稍稍复杂一丢丢的一步啦~
第三步 锚点滚动时,导航栏也要跟着动哦,来而不往非礼也~
这一步,我的思路是这样子滴:
1. 在页面挂载后(onMounted),先拿到所有锚点的offsetTop,从小到大放到一个数组offsetTopList里方便后面使用;
2. 监听可滚动父元素的scroll事件,编写sroll的处理方法srollHandle;
3. 从大到小反向遍历数组offsetTopList,用滚动时获取的offsetTop值和遍历到的值做对比,只要大于等于遍历到的值,就结束遍历,这也是我发现的比较省事的方法(如果有更好的方法欢迎各位大佬在评论区指点一下,我偷偷学习一下);
4. 结束遍历的时候记得要记录当时的锚点哦,这样导航栏才可以根据这个锚点设置对应的高亮项。;
具体代码如下:
const scrollHandle = ({ target }) => {
const curScrollTop = target.scrollTop
let flag = true
const len = offsetTopList.length
for (let i = len - 1; i >= 0; i--) {
const curReference = offsetTopList[i].offsetTop // 当前参考值
if (flag && curScrollTop >= curReference - 10) {
flag = false
sidebarStore.setAnchor(offsetTopList[i].anchor)
}
}
}
小结
到这里,其实关于锚点定位的关键步骤就已经完成了,其中待优化的点就是滚动时处理方法得加下节流处理,不然还蛮消耗性能的。没做过又感兴趣的小伙伴也可以试试哦~
本文关键字
1. scrollTo
2. offsetTop
demo源码在此! 溜了溜了