从 Chrome 129 开始,您可以使用 JavaScript 中的 scrollSnapChange
和 scrollSnapChanging
事件。通过实现内置的贴靠事件,之前不可见的贴靠状态将在适当的时间变得可操作且始终正确。如果没有这些事件,会给您带来不便。
在 scrollSnapChange
之前,您可以使用交叉观察器来查找哪个元素越过了滚动端口,但确定哪些元素被贴靠仅限于某些情况。例如,您可以检测固定项是否填满滚动端口或填满滚动端口的大部分区域。为此,您需要观察滚动区域的相交元素,然后根据哪个项占用了大部分滚动区域,假定这是贴靠目标,然后等待 scrollend
并对贴靠的项目(贴靠目标)执行操作。
不过,在 scrollSnapChanging
之前,我们无法知道何时会发生贴靠目标更改,也无法知道更改为何值(例如在滚动快速滑动时)。
好消息!有了这些新活动,用户可以快速轻松地获取这些信息。这将解锁滚动贴靠互动,使其超出其当前功能,并支持滚动贴靠关系和全新界面反馈场景的编排。
scrollSnapChange
只有在滚动手势导致新的固定目标被停靠且按以下顺序发生时,此事件才会触发
- 滚动停止后。
- 在
scrollend
之前。
此事件会在滚动完成时(即 scrollend
之前)触发,并且仅当停靠在新的固定目标上时才会触发。这样,当滚动手势完成时,事件会感觉是延迟触发或恰到好处触发。
scroller.addEventListener('scrollsnapchange', event => {
console.log(event.snapTargetBlock);
console.log(event.snapTargetInline);
})
scroller.onscrollsnapchange = event => {
console.log(event.snapTargetBlock);
console.log(event.snapTargetInline);
}
该事件会将事件对象上的固定项公开为 snapTargetBlock
和 snapTargetInline
。如果滚动条仅限水平滚动,则 snapTargetBlock
属性将为 null
。该属性的值将是元素节点。
ScrollSnapChange 的特有细节
在用户松开手势后才会触发
手指静止在屏幕上或将手指放在触控板上,表示用户的手势尚未完成滚动,这意味着滚动尚未结束,这意味着贴靠目标尚未更改,正在等待用户完成整个手势。
如果贴靠目标未更改,则不会触发
此事件用于捕获卡顿变化,如果卡顿目标未发生变化,则不会触发此事件,即使用户与滚动条互动也是如此。不过,用户实际上确实滚动了,因此在滚动完成后,系统仍会触发 scrollend
事件。
scrollSnapChanging
一旦浏览器确定滚动手势已或将会产生新的固定目标,此事件就会触发。它会立即触发,并在滚动期间触发。
scroller.addEventListener('scrollsnapchanging', event => {
console.log(event.snapTargetBlock);
console.log(event.snapTargetInline);
})
scroller.onscrollsnapchanging = event => {
console.log(event.snapTargetBlock);
console.log(event.snapTargetInline);
}
该事件会将事件对象上的固定项公开为 snapTargetBlock
和 snapTargetInline
。如果滚动条仅限垂直滚动,则 snapTargetInline
属性将为 null
。该属性的值将是元素节点。
scrollSnapChanging 的唯一详细信息
在执行滚动手势时提前且经常触发
与等待用户执行完整滚动手势的 scrollSnapChange
不同,此事件会在用户用手指滚动或使用触控板滚动时快速触发。假设用户在不抬起手指的情况下慢速滚动,只要用户在多个可能的固定目标上平移,scrollSnapChanging
就会在手势期间多次触发。每次用户滚动时,如果浏览器确定在松开手指后会停留在新的固定目标上,系统就会触发该事件,以告知您是哪个元素。
不会在完成新贴靠目标的过程中触发所有贴靠目标
此外,考虑一个抛掷,即用户做出一次跨越多个贴靠目标的滚动抛掷手势;此事件将触发一次,并且将静置在一个目标上。所以,它虽然很急,但并不浪费,所以能尽快为你提供击杀目标。
使用场景和示例
这些事件可实现许多新的用例,同时使当前模式更易于实现。一个典型示例是启用快拍触发的动画。在 snap 项是 snap 目标时,根据上下文显示 snap 项、snap 项的子项或关联信息。
以下模式展示了一些用例,可帮助您立即提高工作效率。
突出显示赞誉
此示例会宣传或视觉上聚焦于拍摄的赞誉,
scroller.onscrollsnapchange = event => {
scroller.querySelector(':scope .snapped')?.classList.remove('snapped')
event.snapTargetInline.classList.add('snapped')
}
显示已固定项的字幕
此示例显示了已固定项的标题。此演示包含这两种事件,以便您了解 scrollSnapChange
和 scrollSnapChanging
之间的时间和用户体验差异。
为已固定的演示文稿幻灯片的子项添加一次动画
此示例会知道新幻灯片何时到达并停留在屏幕上,这时非常适合对内容进行一次动画处理。
document.addEventListener('scrollsnapchange', event => {
event.snapTargetBlock.classList.add('seen')
})
在滚动条中同时在 x 轴和 y 轴上进行贴靠
滚动贴靠适用于允许水平和垂直滚动的滚动条。此演示会在您滚动网格时同时显示 scrollSnapChanging
和 scrollSnapChange
目标。此演示将说明浏览器贴靠到的元素如何并不是您想象的。
两个已链接的滚动条
此演示包含两个滚动贴靠容器,其中一个是链接的概要列表,另一个是实际的分页内容。借助新的 scrollSnapChanging
事件,您可以轻松地双向关联这些项的固定状态,以便它们始终保持同步。
OKLCH 颜色选择器
此演示包含 3 个滚动条,每个滚动条都代表 OKLCH 中的不同颜色通道。贴靠项与其相关的单选组同步,并且可以从封装输入的表单中检索数据。对于鼠标或触摸用户,您可以滚动到所需的值。对于键盘用户,您可以使用 Tab 键和箭头键。对于屏幕阅读器,它只是一个表单。
快速捕获动画效果的动态枢纽
此演示版使用 scrollsnapchange
通过贴靠触发的转场逐步增强了滚动贴靠体验。
使用以下 JavaScript 检查是否支持事件:
if ('onscrollsnapchange' in window) {
// ok to use snap change
}
可滚动的标尺输入
此演示采用可滚动标尺作为为数字输入选择长度的替代方式。直接在数字输入框中输入值或滚动到所需尺寸。changing 事件用于在用户执行手势期间清除选择,而 change 事件用于更新状态并确认用户的选择。
封面照片
此演示基于 Bramus Van Damme 对著名 macOS 封面流的出色滚动驱动型动画再现(视频教程)。独特的是,scrollSnapChanging
用于隐藏专辑标题,scrollSnapChange
用于显示标题。这些事件有助于协调以极速方式隐藏旧标题并以延迟方式显示新标题。
更多有助于激发创意的想法
现在,了解哪个元素即将贴靠以及哪个元素已主动贴靠并不容易,现在有很多新的可能性!以下是一些有助于激发创意和发现更多用例的想法:
- 触发延迟加载,也称为“snapchange 触发的渲染”或“数据提取”。
- 与较大图片相关联的幻灯影片缩略图。
- 为已固定的视频缩略图切换视频预告片的播放/暂停状态。
- Google Analytics 跟踪
- 滚动式讲述
- “幸运轮”界面/用户体验
- 贴靠目标会获得锚定的提示。
- 点按即可自动对齐
- 贴靠即可显示
- 快拍时发出提示音
- 滑动界面
- 可滑动的标签页或轮播界面
进一步研究
Chrome 团队非常期待听到您使用这些新 API 构建的内容,并希望这些 API 有助于简化滚动体验。