聊聊页面中的锚点效果和回到顶部

页面中的锚点各位想必都“了如指掌”,其基于a连接“同页面跳转”和“id属性标签的历史问题”。javascript

可能有人不知道的是:HTML中的“id”很是神奇:id属性的元素不只能够在js中直接使用,而没必要先获取;还能够和url相关联。
直接用id访问是旧版本js遗留下来的特性,浏览器会创建window实例的id同名属性,这是为了兼容旧的网页。但不要依赖这个特性,在含有特殊字符或者和window实例的其余属性有冲突时可能失效。css

咱们都知道,锚点应该这样用:html

<a href="这里写#号+id名">去这里</a>

<div id="上面a中引用的id名">我是目的地</div>

如此即可。java

可是这里面有两个小问题:web

  1. 使用锚点后url中也会带有href中的字符串(#号+id名)
  2. 由于是相似跳转方式,因此过程很是生硬

好比有的网页中有这样的效果:点击侧边栏或顶部某一个div后整个页面滑动到相应的位置,就像这样——
js点击滚动对应区域浏览器

之前来讲用锚点确定是不现实的,因此咱们须要找到一个适合的API。dom

按照需求,即点击某个div后对应部分的顶部要“恰好”到窗口可视区的顶部!这里面咱们要考虑的必定是“如何算div的顶部在窗口可视区顶部”。
js提供了一个有趣的API能够完成咱们的需求 —— getBoundingClient() ,它至关因而封装了client API并把它应用在普通元素上,经过它咱们能获得此元素距离可视区顶部、左边的距离,好比:
getBoundingClient-APIsvg

而且根据上一篇文章(点击阅读文章)中所提,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() 定时器的清除!
若是上方代码去掉第1四、1五、2六、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"})

scrollIntoView

这里还要提到js中后来新加入的两个原生API:scrollTo(滚动到哪里) 和 scrollBy(滚动多少距离)。这里为啥提到这俩?由于scrillTo这个API能够在ie上使用!它被支持在window上,好比:回到顶部window.scrollTo(0,0);
但这里也只是提一句让各位有个印象,非要用在本文所提场景下则大可没必要。


说到这,前几天惊奇的发现CSS中多了一个控制页面滚动的属性!(去年年末开始支持的)原平生滑滚动定位 —— scroll-behavior ,它有两个值:

  1. auto:初始值。啥也没有。
  2. smooth:做用在滚动容器元素上,可让容器内的滚动变得平滑。

好比在笔者文章中屡次出现的tab框切换,若是你只设置了父容器的 overflow:hidden; 而子元素采用了相对父元素定位的方式展现(display、opacity、visibility都不行,由于他们本质上都不是经过位置移动展现元素的),那么就能够在父容器上加上一行:scroll-behavior: smooth;

效果贼好,生动了许多!

还有上面说的“回到顶部”(和“锚点”),若是不想用js实现并且又不抗拒url后面的小小“#”的话,其实你能够这么实现:

/** css样式 */
html, body { 
 
    scroll-behavior:smooth; }
<a href="#">返回顶部</a>

包括上面的“锚点效果”也能够这么来~

perfect!


元旦将至,提早祝各位元旦快乐,溜了溜了~

本文同步分享在 博客“行舟客”(CSDN)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索