页面中的锚点各位想必都“了如指掌”,其基于a链接“同页面跳转”和“id属性标签的历史问题”。
我们都知道,锚点应该这样用:
<a href="这里写#号+id名">去这里
a> <div id="上面a中引用的id名">我是目的地
div>
如此便可。
但是这里面有两个小问题:
- 使用锚点后url中也会带有href中的字符串(#号+id名)
- 因为是类似跳转方式,所以过程非常生硬
以前来说用锚点肯定是不现实的,所以我们需要找到一个适合的API。
并且根据上一篇文章(点击阅读文章)中所提,document下的scrollTop API可为我们提供文档流(页面整体区域)向上滚动了多少距离。
笔者在这里再次提醒各位要区分js中inner系、page系、client系、offset系、outer系、screen系…事件,他们的含义各不相同。比如常说的offsetTop/Left,是距离上一级父元素的上/左边距,通常用
if(dom.parentElement)做累加求的是“距离文档流顶部的距离”,就不适用于此处。
将二者结合起来使用,就可以达到:若想要展示的区域在下方,就让文档流不断向上滚动,直到此区域滑动到可视区顶端;反之若想要展示的区域已经滑过,就让文档流不断向下滚动。
/ leftBtn:侧边栏中所有负责页面滚动的div,都有一个class属性为left-btn i:left-btn所属div的下标(第几个) .mao1/2/3:页面中负责“滑到顶部”的div,一般是某一个区域的小标题 */ let leftBtn=document.querySelectorAll(".left-btn") function gotoTop(i,top){
var timer=null; leftBtn[i].onclick=function(){
let scrollTop=document.body.scrollTop ||document.documentElement.scrollTop || window.pageYOffset // 若目标位置在当前位置上方 if(scrollTop>top){
clearInterval(timer) timer=null; timer=setInterval(function(){
scrollTop=scrollTop-90<top?top:scrollTop-90; document.body.scrollTop=document.documentElement.scrollTop=window.pageYOffset=scrollTop if(scrollTop<=top){
clearInterval(timer); timer=null; } },50) // 目标位置在当前位置下方 }else if(scrollTop<top){
clearInterval(timer) timer=null; timer=setInterval(function(){
scrollTop=scrollTop+90>top?top:scrollTop+90; document.body.scrollTop=document.documentElement.scrollTop=window.pageYOffset=scrollTop if(scrollTop>=top){
clearInterval(timer); timer=null; } },50) } } }
使用如:
let one_top=document.querySelector(".mao1").getBoundingClientRect().top let two_top=document.querySelector(".mao2").getBoundingClientRect().top let thr_top=document.querySelector(".mao3").getBoundingClientRect().top gotoTop(0,one_top); gotoTop(1,two_top); gotoTop(2,thr_top);
这样就能达到上面展示的效果了。
这里面需要注意的是:
setInterval()定时器的清除!
如果上方代码去掉第14、15、26、27行,则页面滚动行为会发生错误。看上去似乎是clearInterval失效了!其实这个问题本身是由于js定时器特性产生的。clearInterval是根据定时器本身的标识来进行清除的,如果在期间生成了新的interval,并覆盖timer标识对象,旧有的timer定时器对象并不会被停止和清除,而且标识也会丢失导致再也无法被清除,所以写定时器时一定要注意。建议在调用某个定时器任务的函数的时候,一定一开始就把之前的定时器先清除!
这个问题到这里似乎很好的解决了。但是上面代码毕竟还是太长了,而且里面要进行严格的判断以决定开始和结束(定时器的增加和删除),似乎稍有不妥。
不过别急,js更新了另一个神器 —— scrollIntoView() ,原先这个API的作用就是让指定的div的顶部跳到窗口可视区顶部(从效果上看类似锚点),但是更新后增加了配置参数:
dom.scrollIntoView({
behavior:"smooth" // ! })
这个参数的作用就是“平滑滚动”!不过由于新所以兼容性目前还不算很好,但是也无妨,毕竟它原本的作用还在,可以把新特性当做“只对少数用户更新的体验”。
说完了锚点效果,来说说页面中普遍存在的“回到顶部”。
同样的,之前笔者做社团官网的时候就采用了控制scrollTop不断--的方法。现在看来太麻烦了,用上面提到的 scrollIntoView() API就可完成:
目前大部分官网/网站都采用了在页面顶部(左上角)放一张logo的形式。针对使用这种形式的网站,若是logo所在div不是采用 position:fixed; 的方式固定在顶部的话,我们可以将img外面包裹一层a标签,然后就可以在“回到顶部”按钮的事件中这么写:
document.links[0].scrollIntoView({
behavior:"smooth" }) //或者 直接定位图片 document.images[0].scrollIntoView({
behavior:"smooth"})

这里还要提到js中后来新加入的两个原生API:scrollTo(滚动到哪里) 和 scrollBy(滚动多少距离)。这里为啥提到这俩?因为scrillTo这个API可以在ie上使用!它被支持在window上,比如:回到顶部window.scrollTo(0,0);
但这里也只是提一句让各位有个印象,非要用在本文所提场景下则大可不必。
说到这,前几天惊奇的发现CSS中多了一个控制页面滚动的属性!(去年年底开始支持的)原生平滑滚动定位 —— scroll-behavior ,它有两个值:
- auto:初始值。啥也没有。
- smooth:作用在滚动容器元素上,可以让容器内的滚动变得平滑。
比如在笔者文章中多次出现的tab框切换,如果你只设置了父容器的 overflow:hidden; 而子元素采用了相对父元素定位的方式展示(display、opacity、visibility都不行,因为他们本质上都不是通过位置移动展示元素的),那么就可以在父容器上加上一行:scroll-behavior: smooth;
效果贼好,生动了许多!
还有上面说的“回到顶部”(和“锚点”),如果不想用js实现而且又不抗拒url后面的小小“#”的话,其实你可以这么实现:
/ css样式 */ html, body {
scroll-behavior:smooth; }
<a href="#">返回顶部
a>
包括上面的“锚点效果”也可以这么来~
perfect!
元旦将至,提前祝各位元旦快乐,溜了溜了~
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/199793.html原文链接:https://javaforall.net
