效果
见天猫官网 https://www.tmall.com/
点击瞄点平滑滚动到目标位置
实现原理:点击锚点后,自动计算目标元素进入页面所需滚动的距离,通过计时器递归调用函数,每次执行只滚动一小段距离,看起来便是平滑滚动。
实现方案:
1. 通过添加指定的样式类 link_title 来标记目标位置
<p class="link_title">美丽人生</p>
2. 点击锚点时,传入目标位置在所有添加了样式类 link_title 的元素构成的数组的下标
<div @click="scrollToLinkTitle(2)">美丽人生</div>
// 平滑滚动到指定标题——根据含样式类 class="link_title" 的所有元素构成的数组的下标 scrollToLinkTitle(index){ // 获取含样式类 class="link_title" 的所有元素,得到一个数组(列表) let titleList = document.querySelectorAll('.link_title') // offsetTop为元素顶部与整个文档顶部间的距离 let offsetTop = titleList[index].offsetTop; // offset为平滑滚动结束后,元素顶部与显示屏顶部间的距离,默认为0,页面滚动到标题触顶 let offset=70 offsetTop -= offset // scrollTop为显示屏顶部与整个文档顶部间的距离 let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 步长(时长500ms,每10ms一跳,共50跳) let step = Math.abs(offsetTop-scrollTop) / 50; if (offsetTop > scrollTop) { // offsetTop > scrollTop 时元素在显示屏下方时,滚动条需下滑 // scrollTop需增加(offsetTop-scrollTop) smoothDown(); } else { // offsetTop < scrollTop 时元素在显示屏上方时,滚动条需上滑 // scrollTop需减少(scrollTop - offsetTop) smoothUp(); } // 向上平滑滚动 function smoothUp () { if (scrollTop > offsetTop) { scrollTop -= step; document.body.scrollTop = scrollTop; document.documentElement.scrollTop = scrollTop; setTimeout(smoothUp, 10); } else { document.body.scrollTop = offsetTop; document.documentElement.scrollTop = offsetTop; } } // 向下平滑滚动 function smoothDown () { if (scrollTop < offsetTop) { scrollTop += step; document.body.scrollTop = scrollTop; document.documentElement.scrollTop = scrollTop; setTimeout(smoothDown, 10); } else { document.body.scrollTop = offsetTop; document.documentElement.scrollTop = offsetTop; } } },
点击平滑滚动到页面顶部
// 平滑滚动到顶部 toTop(){ let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; let step = 50 // 实现滚动效果 const timer = setInterval(() => { scrollTop -= step; document.body.scrollTop = scrollTop; document.documentElement.scrollTop = scrollTop; if (scrollTop <= 0) { clearInterval(timer); } }, 10); },
锚点随页面滚动高亮显示
实现原理:
- 监听页面滚动,实时获取滚动条的位置
- 根据滚动距离,判断第几个目标元素滚动到屏幕中
- 通过动态绑定样式,高亮显示目标元素对应的锚点
实现方案:
1. 监听页面滚动
mounted() { this.$nextTick( () => { // 监听页面滚动事件 window.addEventListener("scroll", this.scroll) } ) },
2. 触发滚动事件,计算出需高亮显示的锚点下标 activeNav
1. // 高亮显示的锚点下标 2. activeNav: null,
//页面滚动时触发 scroll() { // scrollTop为显示屏顶部与整个文档顶部间的距离 let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 获取含样式类 class="link_title" 的所有元素,得到一个数组(列表) let titleList = document.querySelectorAll('.link_title') // 将每个目标元素顶部与整个文档顶部的距离,以及显示屏顶部与整个文档顶部间的距离都存入到一个数组中 let offsetTopList = [scrollTop] titleList.forEach(item => { offsetTopList.push(item.offsetTop-300) }) // 对数组进行排序(默认从小到大) offsetTopList.sort((a,b)=>{ return a - b; } ) // 当第一个目标元素滚入屏幕后,查询当前滚动的位置在数组中的下标,对应的便是需高亮显示的锚点下标 if(scrollTop>=offsetTopList[0]){ this.activeNav = offsetTopList.indexOf(scrollTop) } },
3. 动态绑定样式,实现高亮对应的锚点
<div @click="scrollToLinkTitle(2)" :class="{'activeNav2':activeNav===2}"> 美丽人生 </div>
.activeNav2{ background: deeppink; }
其他参考资料
vue实现滚动监听,点击瞄点平滑滚动,控制内嵌滚动条滚动
https://blog.csdn.net/weixin_30580341/article/details/97331000
vue2.0模拟锚点实现定位平滑滚动
https://blog.csdn.net/weixin_30257433/article/details/99923910