在实现开发中,回到顶部是一个很常见的需求,基本上每个 ui 框架都提供了这个功能,如果开发中需要这个功能,最好是直接使用框架的,毕竟框架的功能都经过了测试,相比自己实现可以避免一些坑。但对于一些小型项目,特别是 h5 网页之类的,为了启动速度,单独引入 ui 框架过于奢侈。本文主要探讨回到顶部的实现方法。
修改scrollTop
scrollTop是一个可修改的属性, 在chrome浏览器中, 可以通过 document.documentElement.scrollTop 访问和修改, 只要将其值设置为0即可。
但是, 这个目前还不完美, 设置了这个后,直接就回到顶部了, 很突兀。很自然地我们会想到, 如果把这个过程分为多个阶段, 每个阶段只步进一小段距离, 就可以了。
因此, 可以写出下面的函数
const scrollToPosition = (distance, time) => {
// st为函数执行时滚动条到文档顶部的距离
const st = document.documentElement.scrollTop
// 需要滑动的距离
const need = st - distance
// 循环时间,值越小越耗性能
const loopTime = 20
// 循环次数
let loopCount = time / loopTime
// 每次步进的距离
const step = need / loopCount
const scrollTimer = setInterval(() => {
if (loopCount > 0) {
// 此项设置是为了精准定位
loopCount !== 1 ? document.documentElement.scrollTop -= step : document.documentElement.scrollTop = distance
loopCount--
} else {
clearInterval(scrollTimer)
}
}, loopTime)
}
const backToTop = () => {
scrollToPosition(0, 200)
}
在使用过程中, 由于当时的scrollTop可能为小数, 也可能设置的time无法整除, 导致出现了一点小小的偏差。函数执行结束时的scrollTop与目标scrollTop有偏差, 不过不会太大, 通常在10px左右, 因此, 在最后一次不步进直接设置为目标scrollTop, 就可以避免这种偏差。
a 标签锚点定位
a标签通过设置href, 类似 <a href="#block">a tag</a> 即可使得id为block的div出现在视窗的顶部, 因此可以通过放置于顶部的空div来实现回顶效果。当然, 此时是没有动画效果的, 好在css提供了一个属性 scroll-behavior: smooth;
以下为MDN的描述
当用户手动导航或者 CSSOM scrolling API 触发滚动操作时,CSS 属性 scroll-behavior 为一个滚动框指定滚动行为,其他任何的滚动,例如那些由于用户行为而产生的滚动,不受这个属性的影响。在根元素中指定这个属性时,它反而适用于视窗。
我们只需要在需要回到的地方使用这个属性接口, 经过实测, 在普通的html文件中, 在body处设置是无效的, 因此可以指定一个div来模拟文档。
.scroll-box{
overflow-y: scroll;
scroll-behavior: smooth;
height: 100vh;
}
另外, 在这个容器内, 直接将scrollTop设置为0即document.querySelector('.scroll-box').scrollTop = 0也会触发动画效果。用a标签主要是提供了一种不需要使用JavaScript的方法。
使用scrollIntoView
这是一个实验中的功能, 如果你开发的项目需要兼容老旧的浏览器, 我不建议你用它。
以下为MDN的描述
Element.scrollIntoView() 方法让当前的元素滚动到浏览器窗口的可视区域内。
具体用法建议直接查看mdn文档, 此处贴一下用法
<div id="top-block"></div>
<div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
<script>
function backToTop() {
document.querySelector('#top-block').scrollIntoView({
behavior: 'smooth',
block: 'start'
})
}
</script>
使用scroll api(推荐)
相比 scrollIntoView,scroll 使用上更加简洁,详情可参考文档
const toTop = () => {
scroll({
left: 0,
top: 0,
behavior: 'smooth',
});
}
扩展:锚点定位的实现
- 使用上文的
scrollToPosition函数, distance为需要定位的div的offsetTop, 前提是该div的offsetParent为body - 直接使用
scrollIntoView
如果本文帮助了你, 请给我点个赞吧!!!