前言
页面平滑滚动是网页一种常见的效果。那如何用原生的JS实现这也效果呢?
原理
平滑滚动的原理其实很简单。无非就是让页面一种肉眼可见的速度从当前位置滚动到指定位置。故而,要实现平滑滚动效果,我们就要知道“起始位置”、“结束位置”以及“如何让页面从一个点到另一个点”。
获取起始位置和终点位置
想要获取起始位置和终点位置,那就必须确定参考点。在网页中,常用的参考点是页面左上角。(注意,我这里所要实现的平滑滚动效果是在Y轴上进行的。故而,参考下就只需取页面左上角y轴的值。也就是页面顶部。)
1、获取起始(当前)位置
页面元素有一个属性scrollTop
,通过此属性可以获取或者设置对象的最顶部到对象在当前窗口显示的范围内的顶边的距离,也就是元素滚动条被向下拉动的距离。所以,借助该属性,我们可以获取起始(当前)位置。代码如下:
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
2、获取终点位置
除了属性scrollTop
,还有offsetTop
属性:
此属性可以获取元素的上外缘距离最近采用定位父元素内壁的距离,如果父元素中没有采用定位的,则是获取上外边缘距离文档内壁的距离。
我们可以这样获取终点位置:
const tragetElemPostition = document.querySelector(traget).offsetTop;
想了解更多的这方面的属性可查看:https://blog.csdn.net/q67982154/article/details/51611989
JS滚动页面
JS自带一个window方法:scrollTo()
可以实现滚动到文档中的一组特定坐标,它可以接受一组坐标。用法详解:点击此处查看
代码如下:
window.scrollTo(0, tragetElemPostition);
自此,借助上面三个工具,我们就可以实现页面滚动了。但是,只是这样的话,页面滚动并没有平滑滚动的效果,也只会立即闪现的你所给的坐标。故而,我们就需要加平滑滚动的特效。
添加平滑滚动的特效
其实平滑滚动的特效无非就是让它滚动慢一点,让我们肉眼可见就好。
但是window.scrollTo()
只会傻乎乎的立即从一点到另一点,这是无法改变的。那既然它不知变通,那就有我们来变通。我们可以将坐标拆分成许多段,不要一步到位就好了。代码如下:
const step = function() {
// 距离目标滚动距离
let distance = tragetElemPostition - scrollTop;
// 目标需要滚动的距离,也就是只走全部距离的五分之一
scrollTop = scrollTop + distance / 5;
if (Math.abs(distance) < 1) {
window.scrollTo(0, tragetElemPostition);
} else {
window.scrollTo(0, scrollTop);
setTimeout(step, 20);
}
};
就此,实现了页面平滑滚动的效果。代码整合如下:
scrollIntoView(traget) {
const tragetElem = document.querySelector(traget);
const tragetElemPostition = tragetElem.offsetTop;
// 当前滚动高度
let scrollTop =
document.documentElement.scrollTop || document.body.scrollTop;
// 滚动step方法
const step = function() {
// 距离目标滚动距离
let distance = tragetElemPostition - scrollTop;
// 目标需要滚动的距离,也就是只走全部距离的五分之一
scrollTop = scrollTop + distance / 5;
if (Math.abs(distance) < 1) {
window.scrollTo(0, tragetElemPostition);
} else {
window.scrollTo(0, scrollTop);
setTimeout(step, 20);
}
};
step();
}
实现平滑滚动的新方法
除了上面的方法,近来出了一个更为简便的方法实现这一效果:scrollIntoView()
借助该方法实现平滑滚动效果只需要简单的几句代码:
target.scrollIntoView({
behavior: "smooth"
});
但是呢!既然是新特性,就会存在某些浏览器不兼容的情况(IE不行(<—— _<——))。
为此,我们可以做如下调整:
scrollIntoView(traget) {
const tragetElem = document.querySelector(traget);
const tragetElemPostition = tragetElem.offsetTop;
// 判断是否支持新特性
if (
typeof window.getComputedStyle(document.body).scrollBehavior ==
"undefined"
) {
// 当前滚动高度
let scrollTop =
document.documentElement.scrollTop || document.body.scrollTop;
// 滚动step方法
const step = function() {
// 距离目标滚动距离
let distance = tragetElemPostition - scrollTop;
// 目标需要滚动的距离,也就是只走全部距离的五分之一
scrollTop = scrollTop + distance / 5;
if (Math.abs(distance) < 1) {
window.scrollTo(0, tragetElemPostition);
} else {
window.scrollTo(0, scrollTop);
setTimeout(step, 20);
}
};
step();
} else {
tragetElem.scrollIntoView({
behavior: "smooth",
inline: "nearest"
});
}
}
感觉代码更长了!╮(╯﹏╰)╭
但是新特性实现的效果可能会比自己好点,还是要用的。
以上就是关于原生JS实现页面平滑滚动的讲解了。
对了,关于新特性可查看博客:CSS scroll-behavior和JS scrollIntoView让页面滚动平滑