异步平移和缩放 (APZ) 正式上线于 Firefox Quantum,这意味着所有用户都能体验到流畅、无卡顿的滚动!我们之前 在这篇文章中介绍了 APZ,但这里是对它的工作原理进行复述。
到目前为止,滚动一直是主 JavaScript 线程的一部分。这意味着当 JavaScript 代码正在执行时,用户无法滚动页面。借助 APZ,滚动与 JavaScript 线程分离,并以独立的方式执行,这使得滚动体验更加流畅,尤其是在移动手机等速度较慢的设备上。有一些注意事项,例如,棋盘格现象,即当滚动速度快于浏览器渲染页面的速度时,但即使是这种现象,对于整体而言,也是为了获得更好的体验而付出的合理代价,在体验中,浏览器保持响应,不会出现卡顿或冻结现象。
到目前为止,在 Firefox 中,我们已经为某些输入方法 (触控板和鼠标滚轮) 成功地实现了 APZ,但在 Quantum 中,包括触摸和键盘在内的所有方法都将得到支持。
这对开发者意味着什么?
scroll
事件将会有短暂的延迟才会触发。- 在某些情况下,浏览器必须禁用 APZ,但我们可以通过代码来防止其中一些情况。
scroll 事件
在没有 APZ 的情况下,当 JavaScript 线程被阻塞时,滚动不会发生,因此不会触发 scroll
事件。但现在有了 APZ,无论线程是否被阻塞,滚动都会发生。
但是,我们需要注意的一点是:现在滚动发生和滚动事件被分发之间会有一个延迟。
通常情况下,这种延迟只有几帧,但有时我们可以通过使用纯 CSS 解决方案而不是 JavaScript 来绕过它。一些依赖滚动事件的常见用例是粘性横幅或视差滚动。
对于粘性横幅(即无论滚动到哪里都保持在相同位置的横幅)而言,已经有一个 CSS 属性可以实现这一点,因此无需通过 JavaScript 来跟踪用户滚动。这就是 position: sticky
!
.banner {
position: -webkit-sticky;
position: sticky;
top: 0;
left: 0;
/* … */
}
注意:您可以查看此处的实时演示.
视差滚动是游戏、电影和动画中一种常见的特效。它通过以不同的速度滚动各个层来营造二维环境的深度错觉。在现实生活中,当您乘坐交通工具时,您可以观察到类似的效应:离道路更近的事物(例如交通标志、树木等)会快速掠过,而离道路较远的事物(例如山脉、森林等)移动速度则慢得多。
在这个演示中,视差滚动仅通过 CSS 实现。如果您滚动页面,您将看到不同“层”上的物体以不同的速度移动:宇宙飞船、文字、星星等等。
使用 CSS 实现视差滚动的技巧是结合使用 perspective
和 translateZ
。当 perspective
的值不为零时,沿 Z 轴的平移会产生元素距离用户更近或更远的错觉。元素越远,它看起来越小,用户滚动时移动速度也越慢。这正是我们实现视差效应所需要的!为了抵消“变小”的视觉效果,我们需要放大元素。
.stars {
transform: translateZ(-4px) scale(5);
/* … */
}
还需要注意的是,perspective
必须应用于包裹所有视差层的容器,而不是应用于层本身。
.parallax-wrapper {
perspective: 1px;
/* … */
}
您可以在 MDN 的Scroll linked effects 页面 或这篇Pure CSS Parallax Websites 文章 中详细了解这些技术。
防止滚动延迟
有时,浏览器需要延迟或禁用 APZ,因为它不知道用户启动滚动的操作是否会被取消(例如,通过在 wheel
或触摸事件上调用 preventDefault
),或者用户焦点是否会切换到应该接收输入而不是滚动的元素。在这些情况下,滚动会被延迟,以便浏览器能够确保一致性。
注意:通过调用 preventDefault
来延迟滚动的事件包括:wheel
、touchstart
、touchmove
,以及已弃用的 DOMMouseScroll
、mousewheel
和 mozMousePixelScroll
。
对于事件,有两种可能的解决方案。
可以将事件监听器附加到真正需要它的元素,而不是在 document
或 window
上全局监听。在这种解决方案中,只有当该元素触发事件时,APZ 才会被延迟,而不会影响页面的其他部分。
另一种可能的解决方案是在事件监听器中将 passive
标志设置为 true
。通过使用此标志,我们告诉浏览器,我们不会在该事件的处理程序中调用 preventDefault
,因此它知道滚动将发生,并且不需要等到回调执行完毕才能开始滚动。
container.addEventListener('touchstart', function () {
// your handler here
}, { passive: true });
您可以在 MDN 上阅读更多关于 提高滚动性能的这种技术。
请记住,APZ 对键盘输入非常保守,并且对于这种输入方法,它会被禁用的次数很多。例如,click
或 mousedown
可能会改变焦点,而键盘输入可能应该被定向到新获得焦点的元素(例如,按下空格键到 <textarea>
),而不是成为滚动操作。不幸的是,对于这些情况,没有编码解决方法。
总的来说,我认为 APZ 为用户提供的体验,值得付出一些小代价,比如棋盘格现象或事件延迟。如果您对 APZ 有任何疑问,请随时在下方留言!
关于 Belén Albeza
Belén 是一位工程师和游戏开发者,在 Mozilla 开发者关系部门工作。她关心网页标准、高质量代码、可访问性和游戏开发。
一条评论