实现平滑的“回到顶部”功能

1,059 阅读2分钟

话不多说,直接切入正题。

实现平滑的回到顶部或者去到指定的位置,有两种实现方式

  1. CSS
  2. 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)
}

效果图: