滚动驱动型动画性能的案例研究

Yuriko Hirota
Yuriko Hirota

滚动条驱动的动画有什么新变化?

滚动驱动的动画是一种向您的网站或 Web 应用添加互动和视觉吸引力的方式,由用户的滚动位置触发。这是一种非常棒的方法,可以持续吸引用户,并让您的网站在视觉上更具吸引力。

过去,创建滚动驱动的动画的唯一方法是响应主线程上的滚动事件。这会导致两个主要问题:

  • 滚动是在单独的线程上执行的,因此会异步传递滚动事件。
  • 主线程动画容易出现卡顿

这使得创建与滚动保持同步的高性能滚动驱动动画不可能实现或非常困难。

现在,我们将推出一组新的 API 来支持滚动驱动的动画,您可以在 CSS 或 JavaScript 中使用这些 API。该 API 会尝试使用尽可能少的主线程资源,使滚动驱动的动画更易于实现,也更顺畅。目前,以下浏览器支持滚动条驱动的动画 API:

浏览器支持

  • 115
  • 115
  • x

来源

本文将这一新方法与经典的 JavaScript 技术进行了比较,以展示使用新 API 可以有多么简单、流畅的滚动驱动动画。

滚动驱动的动画 CSS API 与经典 JavaScript

以下示例进度条是使用类 JavaScript 技术构建的。

每当 scroll 事件发生时,文档都会进行响应,以计算用户已滚动至 scrollHeight 的百分比。

document.addEventListener("scroll", () => {
  var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
  var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
  var scrolled = (winScroll / height) * 100; 
  document.getElementById("progress").style.width = scrolled + "%";
})

以下演示显示了将新 API 与 CSS 结合使用时的同一进度条。

@keyframes grow-progress {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

#progress {
  animation: grow-progress auto linear forwards;
  animation-timeline: scroll(block root);
}

新的 Animation-timeline CSS 功能会自动将滚动范围中的某个位置转换为进度百分比,从而完成所有繁杂的工作。

现在,这里有有趣的地方 - 假设您在网站的两个版本上都实现了超繁重的计算,这会占用大部分主线程资源。

function someHeavyJS(){
  let time = 0;
  window.setInterval(function () {
    time++;
    for (var i = 0; i < 1e9; i++) {
      result = i;
    }
    console.log(time)
  }, 100);
}

正如您所预期的,由于主线程资源交集,经典 JavaScript 版本会变得卡顿和迟缓。另一方面,CSS 版本完全不受繁重的 JavaScript 工作影响,并能响应用户的滚动互动。

开发者工具中的 CPU 使用率完全不同,如以下屏幕截图所示。

主线程比较。

以下演示展示了由 CyberAgent 创建的滚动驱动动画的应用。您可以看到,照片会在您滚动时淡入。

新的滚动驱动动画 JavaScript API 与传统 JavaScript

新 API 的优势不仅限于 CSS。您也可以使用 JavaScript 制作丝滑的滚动驱动的动画。请看以下示例:

const progressbar = document.querySelector('#progress');
progressbar.style.transformOrigin = '0% 50%';
progressbar.animate(
  {
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    fill: 'forwards',
    timeline: new ScrollTimeline({
      source: document.documentElement,
    }),
  }
);

这样,您只需使用 JavaScript 即可创建上一个 CSS 演示中显示的进度条动画。其底层技术与 CSS 版本相同。该 API 会尝试使用尽可能少的主线程资源,使动画比传统 JavaScript 方法更流畅。

此外,这个新 API 还可以与现有的 Web Animations API (WAAPI)CSS Animations API 结合使用,以实现声明性滚动驱动的动画。

更多演示和资源

您可以访问此演示网站,查看滚动驱动的动画的不同实现,还可以比较使用 CSS 和 JavaScript 中的这些新 API 的演示。

如果您有兴趣详细了解新的滚动驱动动画,请参阅这篇文章2023 年 I/O 大会演讲