滚动贴靠事件

Adam Argyle
Adam Argyle

从 Chrome 129 开始,您可以使用 JavaScript 中的 scrollSnapChangescrollSnapChanging 事件。通过实现内置的贴靠事件,之前不可见的贴靠状态将在适当的时间变得可操作且始终正确。如果没有这些事件,会给您带来不便。

浏览器支持

  • Chrome:129.
  • Edge:129。
  • Firefox:不受支持。
  • Safari:不支持。

来源

浏览器支持

  • Chrome:129.
  • Edge:129。
  • Firefox:不支持。
  • Safari:不支持。

来源

scrollSnapChange 之前,您可以使用交叉观察器来查找哪个元素越过了滚动端口,但确定哪些元素被贴靠仅限于某些情况。例如,您可以检测固定项是否填满滚动端口或填满滚动端口的大部分区域。为此,您需要观察滚动区域的相交元素,然后根据哪个项占用了大部分滚动区域,假定这是贴靠目标,然后等待 scrollend 并对贴靠的项目(贴靠目标)执行操作。

不过,在 scrollSnapChanging 之前,我们无法知道何时会发生贴靠目标更改,也无法知道更改为何值(例如在滚动快速滑动时)。

显示一个水平滚动条,其中包含编号的方框作为贴靠目标。左侧是 scrollSnapChange 事件的实时日志,其中以蓝色突出显示了 snapTargetInline。右侧是 scrollSnapChanging 事件的实时日志,其中以灰色突出显示了 snapTargetInline。

试用
https://codepen.io/web-dot-dev/pen/jOjaaEP

好消息!有了这些新活动,用户可以快速轻松地获取这些信息。这将解锁滚动贴靠互动,使其超出其当前功能,并支持滚动贴靠关系和全新界面反馈场景的编排。

scrollSnapChange

只有在滚动手势导致新的固定目标被停靠且按以下顺序发生时,此事件才会触发

  1. 滚动停止后。
  2. 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);
}

该事件会将事件对象上的固定项公开为 snapTargetBlocksnapTargetInline。如果滚动条仅限水平滚动,则 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);
}

该事件会将事件对象上的固定项公开为 snapTargetBlocksnapTargetInline。如果滚动条仅限垂直滚动,则 snapTargetInline 属性将为 null。该属性的值将是元素节点。

scrollSnapChanging 的唯一详细信息

在执行滚动手势时提前且经常触发

与等待用户执行完整滚动手势的 scrollSnapChange 不同,此事件会在用户用手指滚动或使用触控板滚动时快速触发。假设用户在不抬起手指的情况下慢速滚动,只要用户在多个可能的固定目标上平移,scrollSnapChanging 就会在手势期间多次触发。每次用户滚动时,如果浏览器确定在松开手指后会停留在新的固定目标上,系统就会触发该事件,以告知您是哪个元素。

不会在完成新贴靠目标的过程中触发所有贴靠目标

此外,考虑一个抛掷,即用户做出一次跨越多个贴靠目标的滚动抛掷手势;此事件将触发一次,并且将静置在一个目标上。所以,它虽然很急,但并不浪费,所以能尽快为你提供击杀目标。

使用场景和示例

这些事件可实现许多新的用例,同时使当前模式更易于实现。一个典型示例是启用快拍触发的动画。在 snap 项是 snap 目标时,根据上下文显示 snap 项、snap 项的子项或关联信息。

以下模式展示了一些用例,可帮助您立即提高工作效率。

突出显示赞誉

此示例会宣传或视觉上聚焦于拍摄的赞誉,

scroller.onscrollsnapchange = event => {
  scroller.querySelector(':scope .snapped')?.classList.remove('snapped')
  event.snapTargetInline.classList.add('snapped')
}
https://codepen.io/web-dot-dev/pen/dyBZZPe

显示已固定项的字幕

此示例显示了已固定项的标题。此演示包含这两种事件,以便您了解 scrollSnapChangescrollSnapChanging 之间的时间和用户体验差异。

更改
https://codepen.io/web-dot-dev/pen/wvLPPBL

快照更改
https://codepen.io/web-dot-dev/pen/QWXOObw

为已固定的演示文稿幻灯片的子项添加一次动画

此示例会知道新幻灯片何时到达并停留在屏幕上,这时非常适合对内容进行一次动画处理。

document.addEventListener('scrollsnapchange', event => {
  event.snapTargetBlock.classList.add('seen')
})
https://codepen.io/web-dot-dev/pen/rNEYYVj

在滚动条中同时在 x 轴和 y 轴上进行贴靠

滚动贴靠适用于允许水平和垂直滚动的滚动条。此演示会在您滚动网格时同时显示 scrollSnapChangingscrollSnapChange 目标。此演示将说明浏览器贴靠到的元素如何并不是您想象的。

显示水平和垂直滚动条中的方形网格。虚线边框表示 scrollSnapChange 目标,实线边框表示 scrollSnapChange 目标。红色代表 snapTargetInline,蓝色代表 snapTargetBlock。

https://codepen.io/web-dot-dev/pen/qBzVVdp

两个已链接的滚动条

此演示包含两个滚动贴靠容器,其中一个是链接的概要列表,另一个是实际的分页内容。借助新的 scrollSnapChanging 事件,您可以轻松地双向关联这些项的固定状态,以便它们始终保持同步。

https://codepen.io/web-dot-dev/pen/YzoEEXj

OKLCH 颜色选择器

此演示包含 3 个滚动条,每个滚动条都代表 OKLCH 中的不同颜色通道。贴靠项与其相关的单选组同步,并且可以从封装输入的表单中检索数据。对于鼠标或触摸用户,您可以滚动到所需的值。对于键盘用户,您可以使用 Tab 键和箭头键。对于屏幕阅读器,它只是一个表单。

scrollSnapChanging 用于提前将已固定的项与状态同步,而 scrollSnapChange 用于为应用了用户输入的受影响的颜色通道标题添加动画效果。

https://codepen.io/web-dot-dev/pen/OJeOOVG

快速捕获动画效果的动态枢纽

此演示版使用 scrollsnapchange 通过贴靠触发的转场逐步增强了滚动贴靠体验。

使用以下 JavaScript 检查是否支持事件:

if ('onscrollsnapchange' in window) {
  // ok to use snap change
}
https://codepen.io/web-dot-dev/pen/MWMOOae

可滚动的标尺输入

此演示采用可滚动标尺作为为数字输入选择长度的替代方式。直接在数字输入框中输入值或滚动到所需尺寸。changing 事件用于在用户执行手势期间清除选择,而 change 事件用于更新状态并确认用户的选择。

https://codepen.io/web-dot-dev/pen/LYKOOpd

封面照片

此演示基于 Bramus Van Damme 对著名 macOS 封面流的出色滚动驱动型动画再现视频教程)。独特的是,scrollSnapChanging 用于隐藏专辑标题,scrollSnapChange 用于显示标题。这些事件有助于协调以极速方式隐藏旧标题并以延迟方式显示新标题。

https://codepen.io/web-dot-dev/pen/Bagmmog

更多有助于激发创意的想法

现在,了解哪个元素即将贴靠以及哪个元素已主动贴靠并不容易,现在有很多新的可能性!以下是一些有助于激发创意和发现更多用例的想法:

  • 触发延迟加载,也称为“snapchange 触发的渲染”或“数据提取”。
  • 与较大图片相关联的幻灯影片缩略图。
  • 为已固定的视频缩略图切换视频预告片的播放/暂停状态。
  • Google Analytics 跟踪
  • 滚动式讲述
  • “幸运轮”界面/用户体验
  • 贴靠目标会获得锚定的提示。
  • 点按即可自动对齐
  • 贴靠即可显示
  • 快拍时发出提示音
  • 滑动界面
  • 可滑动的标签页或轮播界面

进一步研究

Chrome 团队非常期待听到您使用这些新 API 构建的内容,并希望这些 API 有助于简化滚动体验。

资源: