话不多说,直接切入正题。
实现平滑的回到顶部或者去到指定的位置,有两种实现方式
- CSS
- JavaScript
CSS实现
主要是通过CSS属性scroll-behavior
来实现,我们来看代码:
<!-- html -->
<!DOCTYPE html>
<html lang="zh-CN" id="html">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 设置需要滚动到的元素的 scroll-behavior 属性,
这里我们设置了 html 元素(一般来说,如果是回到顶部的话,
设置body和html的scroll-behavior属性,去到指定位置,
则设置那个元素的scroll-behavior属性) */
#html {
scroll-behavior: smooth;
}
.to-top {
display: block;
position: fixed;
width: 36px;
height: 36px;
bottom: 50px;
right: 100px;
background-color: #ddd;
color: #fff;
border: 1px solid #f4f5f7;
border-radius: 10px;
font-size: 13px;
text-decoration: none;
text-align: center;
}
</style>
</head>
<body>
<div>
<br />
......
<br />
</div>
<!-- 利用 a 标签,来导航到某个锚点,如果没有设置
scroll-behavior: smooth 属性,浏览器会一瞬间就导航到了
#html 位置,因为scrioll-behavior的默认值是auto(立即滚动),
而smooth是平滑滚动的意思 -->
<a href="#html" class="to-top">回到顶部</a>
</body>
</html>
下面是效果图:
但是scroll-behavior
属性在 IE(旧版Edge不支持,新版的Edge支持) 和 Safari 浏览器下都不支持,所以想要兼容这两个浏览器的话,就必须用到 JavaScript 来实现了。
JavaScript实现
windwo
对象上有一个requestAnimationFrame()
方法,在MDN上是这样描述的:
window.requestAnimationFrame()
告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
注意:若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用
window.requestAnimationFrame()
什么是==浏览器下次重绘==?浏览器重绘是和显示器的刷新率有关的。大部分显示器的刷新率是 60Hz ,就是 1000 / 60 = 16.67ms
刷新一次,浏览器的重绘的间隔就是 16.67ms ,由于人眼的视觉原因,看起来是在流畅的运动。window.requestAnimationFrame()
还有另一个特异功能,如果浏览器没有处于激活状态(浏览器被隐藏或者最小化),浏览器是不会执行window.requestAnimationFrame()
的动画的,直到浏览器被激活,才继续执行之前没完成的动画。
下面就来实现“回到顶部”功能。
const toTopBtn = document.getElementById('to-top')
toTopBtn.addEventListener('click', function () {
// 浏览器不支持 requestAnimationFrame ,用 setTimeout 代替
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = function (cb) {
setTimeout(cb, 16.67)
}
}
window.requestAnimationFrame(toTop)
})
function toTop() {
// 当前位置距离顶部的距离.有些浏览器使用 document.body.scrollTop 获取滚动条高度(比如旧版的
// Edge)
const currentPosition = document.documentElement.scrollTop || document.body.scrollTop
const position = Math.floor(currentPosition / 1.3)
if (currentPosition <= 0) return
window.scrollTo(0, position)
window.requestAnimationFrame(toTop)
}
效果图: