权衡 SVG 动画技巧(含基准测试)

Avatar of Sarah Drasner
Sarah Drasner

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 $200 免费积分!

以下是 Sarah Drasner (@sarah_edo) 的客座文章。Sarah 一直在研究并 发表关于动画的演讲。我迫不及待地想让她在这里分享一些研究成果,这次重点关注 SVG 动画和您可以用来实现它的不同技术选择。

在使用多种 SVG 动画技术几个月后,我可以为您提供一个基本概述,以便您可以自行比较它们。使用每种方法都有很好的理由。希望这篇文章可以帮助您找到适合工作的正确工具。

我们将通过对功能的基本比较。然后我们将深入了解它们的执行效果。包含两个不同的基准测试。一个是来自 Chrome DevTools 时间轴记录的,另一个是从屏幕测量视觉记录。

虽然用 CSS 样式化的 HTML 元素在动画中往往表现得更好,但 SVG 具有能够绘制任何内容并同时保持分辨率无关性的优势。在基准测试中,我们专门处理 SVG 图像。

我们将比较以下 SVG 动画技术

还有无数其他我们没有涵盖的技术,包括 Snap.svg 和较旧的 Raphaël

值得注意的是,CSS 和 SMIL 具有浏览器本身的动画功能,而 GSAP 和 Velocity 是 JavaScript 库,它们操纵一个或多个渲染层以创建动画。

高级比较

CSS

优点

  • 性能良好,尤其是在硬件加速的情况下,但可能不如 DevTools 时间轴报告的那样好。我们将在后面讨论这个问题。
  • 它易于集成到现有的 UI 中,因为您无需加载任何其他资源。
  • CSS 非常适合小型交互,例如悬停状态。
  • 有一些 不错的资源 用于更精细定制的 cubic-bezier 缓动,这使得在开发时更容易直观地看到潜在的结果。

缺点

  • 存在一些向后兼容性问题。@keyframes 在 IE9 或更低版本上无法工作。
  • 您只能在伪状态(例如 :hover:focus)上创建用户交互;需要使用 JavaScript 来处理诸如单击交互之类的事件。
  • 多个动画的链接是通过延迟完成的,这对于较简单的动画效果很好。对于更长的动画,这会使工作流程变得非常复杂。调整时间尺度很困难,尤其是在您需要操纵前几帧时。
  • 物理可能很麻烦。复杂的任务(如摩擦或逐渐减小的弹跳球)充其量非常复杂,最坏情况下根本不可行。
  • 基于百分比的时间比其 JavaScript 对应项更难操作,因为它增加了一层抽象。

    也许您想在动画开始后 1 秒钟执行某些操作。如果 animation-duration 为 3 秒,则这是 33.33% 的关键帧,但在 animation-duration 发生变化时会完全改变。
  • transform-origin 对于 SVG 并不一致

Velocity.js

优点

  • 易于使用的语法。如果您有现有的 jQuery 动画,很容易将其更改为 Velocity,因为它具有相同的样式语法。如果您习惯于 $.animate,那么 $.velocity 也很容易使用。
  • 有许多开箱即用的缓动,并且 弹簧物理 可用。为了进一步改进,还有 步进缓动,您可以在其中传递数组。
  • 语法比 CSS 或 SMIL 更简洁。
  • 您可以使用一行代码来交错多个动画,尤其是在使用可用的 UI 插件时。
  • 比 CSS 有更深的浏览器支持。

缺点

  • 性能远优于现有的 jQuery .animate(),但不如 CSS、SMIL 或 GSAP。
  • 提供对 IE8 的向后兼容性,但不如 GSAP 的兼容性广。

GreenSock (GSAP)

优点

  • 易于使用且语法最简洁。
  • GSAP 的时间轴允许您轻松控制和操作顺序动画;这使得更长的动画比几乎任何其他技术都容易得多。(您可以在同一时间点设置多个补间动画,创建场景,并以不同的时间尺度向前和向后移动 - 基本上是对动画进行动画处理)。
  • 自动硬件加速。性能非常出色 - 与原生渲染一样出色。
  • 应用物理很简单。他们有一个 缓动可视化器 非常有用。
  • 有解决方案 用于解决一些已知的 transform-origin 问题。
  • 提供对 IE6 的支持。比 CSS、SMIL 或 Velocity 的支持范围更广。
  • GreenSock 拥有强大的功能集。如果您需要做某事,GSAP 可能已经考虑到了。为了了解我的意思,请查看这个强大的插件页面,https://greensock.com/plugins/,其中大多数都包含在 TweenMax 版本中(但如果您担心文件大小,他们有一个精简的 TweenLite 版本)。有一些专门的功能,例如沿着路径进行动画(就像 SMIL 可以使用 <animateMotion> 做的那样),拖放交互,甚至与画布一起使用。
  • 他们有一个 jQuery 插件,它将覆盖现有的 jQuery .animate() 并提高性能,而无需额外的编码。

缺点

  • 他们的代码是开源的,但在某些情况下,您可能需要商业用途的许可证。

SMIL

优点

  • 具有直接的声明性语法。
  • 您可以使用与编写它相同的语法来变形路径和形状,这非常直观。这对徽标或变形按钮图标等非常有用。
  • 您可以沿着路径进行动画。
  • 性能非常出色,在视觉显示方面可能优于 CSS、Velocity 和 GSAP。
  • 存在非基于延迟的链接,例如在另一个动画结束时开始动画。
  • 易于添加到现有的 SVG 语法中,无需加载外部资源。

缺点

  • 有人猜测对 SMIL 的支持是否会继续。Chrome 可能将其引入 Web Animations API(以及其他所有内容),但如果这没有实现,它可能得不到很好的维护,因为它目前使用量不足。
  • 链接动画相当有限。
  • 目前不支持 IE。

如果 IE 浏览器支持是一个主要问题,这里有一个非常简单的细分

所有技术都支持现代浏览器,并且在 IE 中部分支持。支持差异在此处说明。此表显示对动画技术的支持,而不是专门针对 SVG 的支持。

基准测试概述

在跨动画方法构建平衡的基准测试时,需要考虑许多因素。它需要是一个非常简单的 SVG - 我使用了一个带有描边的矩形。此外,它需要循环,以便可以观察到随着时间的推移性能的变化。基准测试代码可以在 GitHub 上找到,也可以在 CodePen 上的此集合中找到。

在使用任何技术对 SVG 进行动画处理之前,最好优化 SVG,就像优化任何其他图像一样。一些不错的选择是浏览器内的 SVG 编辑器 或基于节点的 SVGO

这是硬件加速的 CSS 版本

查看 Pen 基准测试 SVG 动画 - CSS 硬件加速,作者是 Sarah Drasner (@sdras),网站是 CodePen

此基准测试包含两个不同的部分:一个基于 Chrome DevTools 时间轴记录,另一个基于屏幕上的视觉记录。这种双重方法是必要的,因为 Chrome 可能无法准确地报告时间轴中的所有处理。GSAP 的 Jack Doyle 在 这段视频 中很好地展示了可能的低估问题。

由于动画效果的呈现很大程度上取决于受众对视觉显示的理解,我包含了每种动画在运行时可能出现的“卡顿”的视觉记录,以及 Chrome DevTools Timeline 的基准测试结果。卡顿是指在创建动画或滚动事件时发生的视觉卡顿现象,目标是实现丝滑流畅的动画。如果您想了解更多关于这方面的信息,JankFree 是一个很好的资源,提供了优化代码的工具和技巧。

并非所有演示都是一样的 - 硬件加速和 CPU

在这些比较中,重要的是要意识到,仅仅使用每种方法构建动画并不能说明全部情况。对于每种技术,都有方法可以硬件加速动画以提高性能。在这个演示中,每种技术都根据动画类型进行了原生加速。例如,可以通过 CSS 将元素在合成器中设置到自己的图层(例如 transform: translateZ(0))来优化 SMIL。但我展示了如何在 SMIL 中直接执行此操作。为了演示性能差异,我还加入了 CSS 和 SMIL 的非硬件加速示例。

所有从库中构建的代码在测试之前都经过库作者的验证和批准。

如何使用 CSS 进行硬件加速

  • 将变换设置为 null,然后使用变换进行移动。
  • 您将它们卸载到 GPU(图形处理单元)。大多数现代浏览器都附带硬件加速功能,但除非它们被告知需要,否则不会使用它。
  • 其他 GPU 加速:backface-visibility: hidden;perspective: 1000; - 防止动画闪烁。
  • 隔离您需要移动或调整的图层。
  • 使用变换进行移动。

如何使用 SMIL 进行硬件加速

  • 使用 <animateTransform> 而不是 <animate> 并设置 x、y、z 值(z 为 0)。
  • 与 CSS 类似,这将元素移动到自己的图层。使用变换进行移动比使用边距或顶部、左侧更有效,因为它不会重新绘制。

如何使用 Velocity 进行硬件加速

  • 使用 translateXtranslateY 进行移动。将元素设置为 translateZ: 0;
  • 确保通过声明动画元素的变量来避免布局抖动,以防止多次查找(这里不适用,但值得一提)。

如何使用 GSAP 进行硬件加速

  • 在演示中,我们将元素设置为 force3D: "true",但 GSAP 现在默认包含此设置。这意味着您无需使用 translateZ: 0; 进行硬件加速,它已经包含在内。
  • 使用 X 和 Y 移动物体比使用边距效果更好。
  • TweenLite 是 GSAP 的轻量级版本,建议将其用于较小的动画。TweenMax 提供循环支持,因此我们在这里使用它。

忠告:一次硬件加速太多图层会产生反效果。每个图层都是一个映射的 GPU 纹理 - 过多的图层会很快耗尽可用资源。因此,明智地使用硬件加速非常重要。

基准测试

以下是 Timeline 基准测试的结果:(较小的条形表示性能更好。)请特别注意“绘制”,因为这是事件中最昂贵的操作。每个基准测试都运行了 5 次以确保一致性,然后取平均值。这里还包含一个硬件加速的 CSS 版本 (HA) 以及非加速版本 (naive),以说明性能受影响的程度。这些测试是在 Chrome 版本 40.0.2214.91(64 位)上运行的 - 截至文章发布日期的最新稳定版本。请注意,版本号可能会改变 Timeline 的报告结果。

这些图表显示了收集数据的比较。每个条形代表总记录时间的百分比。每个基准测试都运行了 5 秒、10 秒和 60 秒的增量。条形越小,性能越好。
这个图表显示了所有收集数据的组合。条形越小,性能越好。请注意 CSS 硬件加速条形,因为之前提到的它可能低估了性能。

重要事项

不透明度和变换的整体性能往往更好,Timeline 报告显示它们在硬件加速的 CSS 中性能“显著”更好。

来源:Google IO 关于 Jank 消除的演讲

由于前面提到的 CSS 动画可能低估性能的可能性,在评估时不能仅仅依靠 Timeline,还应结合视觉效果进行判断,因为受众会根据视觉效果来评价动画。

视觉基准测试

为了完整地了解情况,我还根据视觉效果进行了几个基准测试。为此,我录制了每种技术中循环的第一个完整迭代的屏幕截图,然后使用一个名为 Physmo 的工具来绘制 SVG 元素的每个移动。我绘制了变化率超过 2 帧没有视觉变化的任何时间的比较。这显示了动画看起来暂停的时间,因此显示了卡顿现象。以下是每种技术的表现

正如杰克的演示所示,优化的 CSS 在视觉显示方面并没有真正胜过其他所有技术。SMIL 的变化率最稳定,其次是 GSAP。GSAP、CSS 和 Velocity 的表现与 Timeline 报告的结果基本一致,即它们的性能差异很大。

请注意,屏幕截图技术可能会改变这里的结果。我建议您尝试我创建的演示,或者最好自己编写比较,看看这些技术的表现如何。

基准测试会因上下文而异。使用不同的参数,特别是在加载其他资源时,会影响这些结果。关于不同情况下性能的持续对话对于改进动画技术至关重要。

更复杂的动画

对于简短的动画来说,这很好,但构建更长、更复杂的动画会怎样呢?GSAP 允许您在可调节的时间轴上工作,或者使用多个时间轴 - 您可以调整所有时间轴的时间尺度、更改放置顺序,甚至进行重叠。CSS 不允许您同时重叠不同的变换,这对于非常真实的运动来说是一个大问题。如果您考虑人们如何移动,或者物体如何相互作用,很少会出现所有事件都以线性顺序进行而没有重叠的情况。

在 CSS 动画中,你可以用延迟来链接事件,但当你想要调整其中的一部分,并且它有相应的其他部分时会发生什么呢?然后你必须回溯整个构建过程,并重新计算所有后续部分的数学运算。GSAP 的时间轴为你提供了更多控制这些动画的能力。它们还允许使用诸如物理学之类的功能,这些功能对于实现逼真的动画至关重要。

SMIL 非常适合像变形 SVG 这样的动画,而其他技术都没有以同样的能力提供这种功能。然而,目前尚不清楚该规范是否会随着时间的推移而得到维护,而且由于你必须使用现有的点,因此在同时对许多分散的元素使用这种技术就没有什么意义。

CSS 非常适合页面元素的过渡效果。你在企业网站上更常看到的东西,目标不是炫耀动画,而是更小的效果来增加兴趣或强调变化。如果你需要一点交互,悬停效果和轻量级的滚动库(如 Waypoints)可以轻松实现。

像 GSAP 和 Velocity 这样的动画库非常适合在生产中使用,因为维护工作量和必要的代码量要少得多。Velocity 的性能可能不如其他库,但简单的事实是,你可以用一个词将现有的 jQuery 代码更改为更高效的代码,这真是一个巨大的优势。Velocity 还提供物理学,而 CSS 则没有。GSAP 将其提升了一个档次:你可以使用现有的 jQuery,并简单地添加 GSAP jQuery 插件。它将覆盖你现有的 jQuery,并使其更有效地执行,而无需你更改任何代码。GSAP 还具有物理学、沿路径运动,等等。

由于一些严重的性能缺陷,jQuery 本身不应该再被认为是动画事物的合适方法。

结论

使用建议

  • 对于小的过渡或简单的动画,使用 CSS 动画。你不需要加载其他资源,并且悬停时的小变形可以有利于交互和用户体验。特别是在你不必使用物理学或进行大量堆叠 SVG 变换的情况下,这些变换并不总是必要的。
  • 在将 SVG 彼此变形的情况下(例如,徽标),以及当被动画的对象可以回退到 IE 中的静态图像时,使用 SMIL。
  • 对于现有的 jQuery 动画,使用 Velocity 可以提高性能,而无需更改大量代码。
  • 对于高性能动画或包含多个场景的长尺度动画,使用 GSAP。它解决了浏览器之间 SVG 变换原点一致性的主要问题。GSAP 功能非常强大,但你可以使用更小的版本,而不需要很多花哨的功能,只加载必要的东西。

每个人都有自己的偏好,不可能完全做到客观。在选择工具时要有目的性,因为它们都有特定的权衡取舍,并且在开发环境中上下文很重要。这篇文章作为一个一般比较,帮助开发人员找到最适合他们想要完成的任务的技术。