用 TOC 点击跳转案例学习滚动事件

三葉Leaves Author

'scroll' 定义滚动事件。

关于滚动事件

监听页面滚动

虽然可以监听任何一个元素的滚动,但是通常情况会监听整个页面的滚动。这时候我们对 window 添加监听器就行了。

1
2
3
window.addEventListener('scroll', function () {
...
})

获取已滚动的值

通常情况下,我们需要获取 HTML 中已经滚动的值:

  • 元素.scrollTop 用于具有滚动条的元素节点,且可读写
  • window.scrollY 仅仅用于页面,且只读,不可重新赋值

获取 HTML 元素的固定写法:

1
const html = document.documentElement;

获取 body 元素的固定写法:

1
const body = document.body;

在现代浏览器中,通常都是获取 HTML 的滚动值。然而为了兼容 IE,可以这样写:

1
2
// 当前页面的垂直滚动位置
const scrollY = window.scrollY || document.documentElement.scrollTop || document.body.scrollTop;

下面这个例子,仅仅当已经滚动 100 像素的时候,才会显示盒子:

1
2
3
4
5
6
7
8
9
10
11
12
const div = document.querySelector('div')
// 页面滚动事件
window.addEventListener('scroll', function () {
// 获取html元素写法
// document.documentElement
const n = document.documentElement.scrollTop
if (n >= 100) {
div.style.display = 'block'
} else {
div.style.display = 'none'
}
})

操作页面滚动

  1. 用手拉进度条

真 · 有手就行

  1. window.scrollY 赋值

由于 元素.scrollTop 或者 window.scrollY 取得的值是可读写的,用 JS 操作这个值可以改变元素已滚动的距离(这里的元素通常指 HTML)

  1. window.scrollTo(x, y)

操作页面滚动到某个地方,第一个值通常取 0 ,因为没人喜欢横着滚。

  1. Element.scrollIntoView();

由需要被显示的子元素调用,
这会直接把父容器滚动到该元素的位置。这在制作点击跳转到某个元素的时候会很有用。
括号里可以传入一个对象,比如下面这段代码:

1
expectLife.scrollIntoView({ behavior: 'smooth', block: 'start' });

就会让 expectLife 的父元素滚动到 expectLife 所处的位置,并且以平滑的方式。block: 'start' 决定了元素的顶端将和其所在滚动区的可视区域的顶端对齐。

这其实有点像先获取元素在页面中的位置,再次操作页面滚动到这个位置:

1
2
const n = item.offsetTop;
window.scrollTo(0, n);

关于滚动值的单位

获取到的 document.documentElement.scrollTop 是不带单位的,虽然它的单位就是 px

我一直好奇这种情况下,怎么实现响应式网页设计?其实思路很简单:
用页面内容高度 document.documentElement.scrollHeight 减去一屏的视口高度(因为首屏不需要滚的时候就能看到) document.documentElement.clientHeight,就能得到可滚动的总距离。然后用已经滚动的距离除一下,就能获得已滚动的占比了:

1
2
3
4
5
6
7
8
9
10
// 已滚动距离
const n = document.documentElement.scrollTop;

// 可滚动的总高度
const canScrollHeight =
document.documentElement.scrollHeight -
document.documentElement.clientHeight;

// 已滚动占比
const readedPercent = n / canScrollHeight;
clientHeightoffsetHeight 区别?

两者都是用来获取元素的尺寸,计算时候都不包含 margin ,都包含 padding,区别在于 clientHeight 不含 border。

平滑滚动

有时候想让页面滚动有动画,而不是直接跳过去。

CSS

1
2
3
html {
scroll-behavior: smooth;
}

遗憾的是,似乎操作不了更多行为。

js

函数调用时候加上平滑

可以使用带参数对象的函数调用,同样加上平滑属性。

1
2
3
4
5
6
7
window.scrollTo({
top: document.body.scrollHeight,
behavior: "smooth",
});

// 或者
el.scrollIntoView({ behavior: "smooth" });
使用外部库

考虑使用专业的滚动动画库,如:

  • GSAP (GreenSock Animation Platform): 提供精细控制的滚动动画
  • ScrollMagic: 专门用于滚动交互
  • Lenis: 专注于平滑滚动的轻量库
其他

除此之外,还可以通过 Window.scrollTo() 方法配合 ScrollToOptions 对象实现效果。太复杂,就不写了。

制作 TOC 的几种方式

纯 HTML

HTML 自带一个锚点机制:
URL#item-1 可以跳转到页面中 id="item-1" 的元素。

所以我们只需要这样做:

1
2
3
4
5
6
7
8
9
10
<nav>
<a href="#page-1">1</a>
<a href="#page-2">2</a>
<a href="#page-3">3</a>
</nav>
<scroll-container>
<scroll-page id="page-1">1</scroll-page>
<scroll-page id="page-2">2</scroll-page>
<scroll-page id="page-3">3</scroll-page>
</scroll-container>

然后给被点击的按钮加个超链接就行了。

JS 的 scrollIntoView() 方法

1
2
3
btn.addEventListener("click", function () {
target.scrollIntoView();
});

先计算距离,再跳过去

上面已经说过了,就不解释了

1
2
3
4
btn.addEventListener("click", function () {
const n = target.offsetTop;
window.scrollTo(0, n);
});
  • 标题: 用 TOC 点击跳转案例学习滚动事件
  • 作者: 三葉Leaves
  • 创建于 : 2025-05-21 00:00:00
  • 更新于 : 2025-06-07 19:46:13
  • 链接: https://blog.oksanye.com/f9e94a3b6584/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论