动画技术的比较

Avatar of Sarah Drasner
Sarah Drasner

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

我被问到最多的问题是:您推荐什么动画工具?

使用过很多工具后,我可以告诉您 **没有正确答案**。这是一个复杂的问题,答案也很复杂。这篇文章旨在阐明何时使用什么工具,从而帮助您使用合适的工具完成工作。

如果您是 React 用户,我们也为您准备了内容!请跳至下方 React 部分,我们将分解要使用什么以及如何使用它。

不可能涵盖所有现有的动画库,因此我将重点介绍我使用过或感兴趣的库。请记住,这些是我根据自身经验给出的建议,Web 世界存在很多灰色地带,因此您可能会有不同的体验或意见。这没问题。

原生动画

在讨论任何库之前,让我们先了解一些原生动画实现。大多数库都在底层使用了原生动画技术,因此您对这些技术的了解越多,在抽象化发生时就越能理解正在发生的事情。

CSS

CSS 仍然是我最喜欢的动画方式之一。我使用它已经很多年了,并且继续 成为它的粉丝,因为它 **易读且性能出色**。CSS 动画使您可以使用一组 关键帧 在不同状态之间进行过渡。

优点

  • 您不需要外部库。
  • 性能非常好,尤其是在执行本质上是硬件加速(卸载到 GPU)的操作时。 这是一篇关于相关属性的文章,可以帮助您实现这一点。
  • 预处理器(如 Sass 或 Less)允许您创建变量(用于缓动函数或时间等),您希望这些变量保持一致,以及在函数中使用 :nth-child 伪类以产生交错效果。
  • 您可以使用 原生 JavaScript 监听 onAnimationEnd 和一些其他动画钩子。
  • 沿路径运动 即将推出,这将非常棒。
  • 它易于用于响应式开发,因为您可以使用 媒体查询 修改动画。

缺点

  • 贝塞尔缓动 可能有点限制。由于只有两个控制点来塑造贝塞尔曲线,因此无法产生一些复杂的物理效果,而这些效果对于逼真的运动很有用(但并非总是必要)。
  • **如果您要连续链接三个以上的动画,我建议切换到 JavaScript。** CSS 中的动画排序会因为延迟而变得复杂,并且如果调整时间,您最终需要进行大量重新计算。 查看 Val Head 的这篇示例,它说明了我的意思。 交错效果也更容易用 JavaScript 编写。您可以挂接到我之前提到的原生 JavaScript 事件以解决此问题,但这会导致在语言之间切换上下文,这也不是理想的选择。长而复杂、顺序的动画更容易用 JavaScript 编写和阅读。
  • 对沿路径运动的支持尚未到位。您可以在此处为 Firefox 投票 支持。据我所知,在 Safari 中投票支持的方式更个性化。我注册了 填写错误报告 并请求将 CSS 中的运动路径模块作为一项功能。
  • CSS + SVG 动画在行为上有一些奇怪的特性。例如,在 Safari 浏览器中,不透明度和变换组合可能会失败或产生奇怪的效果。另一个例子是,规范中对变换原点的定义,当顺序应用时,可能会以 非直观的方式 显示。这是规范的编写方式。希望 SVG 2 会对此有所帮助,但目前,CSS 和 SVG 在移动设备上有时需要使用奇怪的技巧才能正常工作。

requestAnimationFrame

requestAnimationFrame (rAF) 是 JavaScript 中 window 对象上可用的原生方法。它非常棒,因为在底层,它会确定您所处环境中动画的适当帧速率,并且只会将其推送到该级别。例如,当您在移动设备上时,它不会像在桌面设备上那样使用那么高的帧速率。当标签页处于非活动状态时,它也会停止运行,以避免不必要地使用资源。因此,
requestAnimationFrame 是一种非常高效的动画方式,我们即将介绍的大多数库都在内部使用了它。requestAnimationFrame 的工作方式类似于递归,在绘制下一帧之前,它会执行逻辑,然后再次调用自身以继续执行。这听起来可能有点复杂,但它实际上意味着您有一系列不断运行的命令,因此它会非常漂亮地为您插值渲染中间步骤的方式。

Canvas

Canvas 非常适合让像素动起来!您在 CodePen 上看到的很多 炫酷效果 都是由 canvas 专家制作的。顾名思义,canvas 提供了一个可视化脚本空间,您可以在其中创建复杂的绘图和交互,所有这些都具有高性能渲染。我们在这里处理的是像素,这意味着它们是 光栅(而不是矢量)。

优点

  • 由于我们不是在 DOM 中移动元素,而是在移动像素块,因此您可以在不降低性能的情况下实现大量复杂的效果。
  • **Canvas 在交互方面非常出色**。您已经在 JavaScript 中,它提供了很多控制权,无需切换上下文。
  • 性能非常好。尤其考虑到您可以创建的内容。
  • 您可以创建任何想要的东西。

缺点

  • 难以使其具有可访问性。您需要使用 React 之类的东西为您创建 DOM,Flipboard 之前曾尝试过,尽管在 他们的案例研究 中,似乎他们还有更多工作要做。不过,如果您有兴趣承担这项任务,这里可能存在一个机会。
  • 我发现使其具有响应性非常不直观。这里我指的是,不仅仅是让小版本在手机上工作,因为它在这方面做得很好。我的意思是根据视口移动、切换和重新组织内容。我相信有一些非常优秀的开发者可以轻松地做到这一点,但我认为它并不十分简单。
  • 它不是视网膜就绪的。与分辨率无关的 SVG 动画不同,我看到的多数 canvas 动画在视网膜显示屏上并不清晰。
  • 调试起来可能很困难。当您构建的内容出现故障时,它会通过显示空白来表明故障,这与在 DOM 中进行动画不同,在 DOM 中,元素仍然存在,只是行为怪异。

SMIL

SMIL 是原生的 SVG 动画规范。它允许您直接在 SVG DOM 中移动、变形甚至与 SVG 交互。使用 SMIL 有很多优点和缺点,但最大的缺点将导致我完全忽略它:**它正在失去支持**。 这是我写的一篇关于如何迁移到支持更好的技术的文章

Web Animations API

Web Animations API 是原生 JavaScript,允许您创建更复杂的顺序动画,无需加载任何外部脚本。或者说,当支持度提高时会是这样。目前,您可能需要一个 polyfill。这个原生 API 的创建是为了补充人们已经在 Web 上使用 JavaScript 创建的众多优秀库和工作。这是为了将 CSS 动画的性能和 JavaScript 中的顺序灵活性整合到一起。如果您有兴趣了解更多信息,有一期 ShopTalk 节目专门介绍了它

优点

  • 顺序动画很容易理解和编写。请查看Dan Wilson 的这个示例,它比较了 CSS 关键帧和 Web 动画 API。
  • 性能似乎正在朝着非常好的方向发展。我还没有很好地测试过,但计划进行测试。(您也可以并且应该进行自己的性能测试)。

缺点

  • 目前支持度并不理想。它还在不断变化,因此在规范仍在发展过程中,我建议谨慎地在生产环境中使用它。
  • GSAP(我们稍后会介绍)的时间轴中还有很多更强大的功能。对我来说,重要的功能包括 SVG 的跨浏览器稳定性和用一行代码就能完成大量顺序动画的能力。

WebGL

您可以使用 WebGL 做一些非常棒的事情。如果有什么东西让您惊叹不已,那么很有可能它是用 WebGL 制作的。它真正擅长的是交互式和 3D 效果。查看一些演示。从技术上讲,它使用的是 canvas,但我喜欢做出区分,因为,我不知道,当名称有助于识别细微差异时,它们就很酷。

优点

  • 惊人的视觉效果
  • 三维意味着一个全新的交互世界
  • 硬件加速
  • VR 的可能性

缺点

  • 比我们之前介绍的其他原生动画更难学习。我做的前两个动画,我以为它们没有工作,因为我的相机指向错误的方向(唉)。与其他我提到的技术相比,真正好的文章和书籍来解释如何使用它也比较少,但是它们正在增长
  • 难以使其响应式。我见过的使用 WebGL 的大多数网站都回退到“请在桌面电脑上查看此网站”的屏幕。

外部库

GreenSock (GSAP)

GreenSock 是我迄今为止最喜欢的库。请理解,这种偏见来自于我使用、尝试过以及在许多不同的动画工具上碰壁的经历,因此当我给出强烈的推荐时,它来自于我的血汗和泪水。我特别喜欢它在 SVG 上的表现GreenSock 动画 API 几乎拥有太多优秀的特性,无法在这里一一列举,但它们提供了文档和论坛供您探索。

优点

  • 对于非原生库来说,它的性能非常出色。也就是说,性能表现得非常好,这非常重要。
  • 顺序工具(如时间轴)既易于阅读又易于编写。调整时间、让多个内容同时触发(使用相对标签)以及用一行代码加快或减慢动画的速度都非常简单。
  • 如果您想做一些花哨的事情,比如动画文本、变形 SVG 或绘制路径,它们还有许多其他插件。
  • 它们在贝塞尔插件中的路径运动具有最长的支持历史。
  • 它解决了 SVG 的跨浏览器问题。感谢这个功能。尤其是在移动端。他们写的一篇文章中有一些关于此方面的信息。
  • 它们提供了非常棒的、非常真实的缓动效果
  • 由于您可以对任意两个整数进行缓动,因此您可以做一些很酷的事情,比如为一些很棒的效果制作 SVG 滤镜动画,甚至可以在 canvas 中使用。您可以动画化任何东西,天马行空。
  • GSAP 是唯一一个允许您使用数量不等的点来变形路径数据的动画库,包括原生的 SMIL。这为运动和移动带来了新的机遇。(如果您想亲眼看看,请在桌面电脑上点击此页面顶部的 logo 上的橙色部分)。

缺点

  • 如果您要将产品转售给多个用户(应用程序和付费访问网站),则需要支付许可费用。这可能不是大多数情况。我还要补充一点,支持这项工作并非坏事。
  • 与任何外部库一样,您需要关注在生产环境中使用的版本。当新版本发布时,升级将需要一些测试(就像任何库一样)。您还需要考虑库的大小。

VelocityJS

VelocityJS 提供了许多 GreenSock 提供的顺序动画功能,但没有那么多的花哨功能。由于以下缺点,我已不再使用 Velocity。Velocity 的语法看起来有点像 jQuery,所以如果您之前一直在使用 jQuery,它会很熟悉。

优点

  • 链接许多动画比 CSS 要容易得多。
  • 对于缓动效果的细化,可以使用阶梯缓动,您可以传入一个数组。
  • 文档非常不错,因此很容易学习和上手。

缺点

  • 性能不太好。尽管有些人声称并非如此,但当我进行自己的测试时,我发现它并没有真正经受住考验。不过,我建议您也进行自己的测试,因为 Web 始终在发展,而这篇文章是时间静止的。
  • GSAP 在性能和跨浏览器稳定性方面提供了更多功能,而且不会增加更多负担。我还想说,jQuery 过去在性能测试中会输,但这在它们采用 RAF 后可能已经改变了,因此 Velocity 并不是说不好,但在比较中它处于劣势。
  • 据我所知,它不再积极维护了。我听说 Julian Shapiro 已将项目移交给其他人,因此它可能在未来某个时候会重新出现。

jQuery

jQuery 本身并不是一个纯粹的动画库,但它有动画方法,而且很多人都在使用它,所以我认为我应该介绍一下它。

优点

  • 许多网站已经加载了它,因此它通常是现成的。
  • 语法非常易于阅读和编写。
  • 它们最近迁移到了 requestAnimationFrame,因此在3.0.0 及更高版本中,性能将比之前更好。

缺点

  • 3.0.0 之前的版本的性能不是很好,不建议使用。我没有以非常正式的方式测试过,但是除了查看 Chrome DevTools 中的重绘和绘制之外,您还可以用肉眼观察到这一点。
  • 在任何版本中都不支持 SVG 动画.
  • jQuery 仅限于 DOM,不像 GSAP 等工具可以作用于任何内容。

Snap.svg

许多人认为 Snap 是一个动画库,但它从未打算成为一个动画库。我本来打算对 Snap 进行性能基准测试,但即使是 Dmitri Baranovskiy(Snap.svg 及其前身 Rafael 的才华横溢的作者)在SVG Immersion Podcast 上也表示,它不是正确的工具,并且在发给我的消息中说

注意:Snap 不是一个动画库,当您需要严肃的动画时,我始终建议与 GSAP 一起使用。

也就是说,jQuery 对 SVG 的支持不是很好,尽管它们现在支持类操作。如果我需要对 SVG 进行任何 DOM 操作,Snap 在这方面非常棒。

最近发布了一个名为SnapFoo 的库,它将 Snap 的领域扩展到了动画。我自己还没有尝试过,但看起来非常酷,值得一试。如果您尝试了,请反馈或在下面发表评论!

Mo.js

这是一个库,由一位名叫LegoMushroom 的很棒的家伙创建。他是一位非常有才华的动画师,并且已经为这个库制作了一些很棒的演示,让我感到非常兴奋。这个库仍在测试版阶段,现在即将发布。如果您有兴趣了解更多信息,我在这里写了一篇关于如何使用它的入门指南

优点

  • 它包含形状、爆发和漩涡等功能,这些功能非常易于使用


    并且为你启动一些东西——所以你不需要成为世界上最好的或最有创意的插画家就能获得不错的效果。
  • Mo.js 提供了一些网络上最好和最漂亮的工具,包括
    播放器、时间线和自定义路径创建器。这本身就是使用它的最令人信服的原因之一。
  • 有几种不同的动画方式——一种是对象,一种是在
    缓动过程中绘制变化——所以你可以选择你觉得更舒服的方式。

缺点

  • 它还没有提供使用 SVG 作为自定义形状父元素的功能(我
    相信 LegoMushroom 正在开发此功能),因此使用坐标系和缩放进行响应式设计不太直观,并且难以在移动设备上实现。不过,这是一种相当高级的技术,你可能不需要它。
  • 它不像 GreenSock 那样修复跨浏览器行为,这意味着
    你可能需要像使用 CSS 一样编写一些 hack。他提到他也正在开发此功能。

Three.js

Three.js 是一款很棒的三维动画工具!查看一些示例。我还没有太多使用它,所以我不太敢对其进行评价,但我计划学习,并在了解更多后更新这篇文章。人们通常将它与原生 WebGL 结合起来讨论。

Bodymovin’

Bodymovin’ 旨在在 Adobe After Effects 中创建动画,你可以轻松导出到 SVG 和 JavaScript。一些演示非常令人印象深刻。我不用它是因为我真的很喜欢用代码从头开始构建东西(所以这对我来说违背了目的),但是如果你更像是一个设计师而不是开发人员,这个工具可能对你来说非常棒。我看到的唯一缺点是,如果你以后需要更改它,则必须重新导出它。这可能是一个奇怪的工作流程。此外,输出的代码通常有点糟糕,但我还没有看到它对 Bodymovin’ 的性能产生太大影响,所以可能没问题。

React 特定工作流

在我们讨论 React 之前,让我们先了解一下为什么我们必须以不同的方式处理 React 中的动画。DOM 代表文档对象模型。它是我们如何使用对象创建结构化文档,我们将这些对象的节点称为树。React 与虚拟 DOM交互,这与原生浏览器 DOM 实现不同,它是一个抽象。

React 使用虚拟 DOM 有很多原因,其中最引人注目的是能够找出发生了哪些变化,并仅更新它需要更新的部分。这种抽象是有代价的,你习惯使用的一些旧技巧在 React 环境中会给你带来麻烦。例如,jQuery 无法与 React 良好地配合使用,因为它的主要功能是与浏览器的原生 DOM 交互和操作。我甚至看到了一些奇怪的 CSS 竞争条件。以下是一些我在 React 工作流中进行良好动画的建议。

React-Motion

React-Motion 是在 React 中进行动画的非常流行的方法,并且社区已经采用它来替代以前最常用的ReactCSSTransitionGroup。我非常喜欢它,但是使用它有一些关键点,如果你不理解,就会让你感到头疼。

React-Motion 与基于游戏的动画非常相似,你为一个元素赋予质量和物理特性并将其发送出去,它到达目的地的时间取决于它本身。这意味着你没有像使用 CSS 或任何其他传统的基于网络的顺序运动那样指定时间量。这是一种思考动画的截然不同的方式。这意味着运动具有看起来非常逼真的能力,这可能非常漂亮。但是 UI 比游戏有不同的需求,因此使用它可能会变得棘手。假设你有两个必须独立触发并在同一时间到达的不同事物。将它们完全对齐可能很困难。

直到最近,还没有可用的排序功能。就在上周,Cheng Lou 添加了onRest,它允许这种回调工作流。在不编写无限循环(糟糕)的情况下编写循环仍然不容易。你可能不需要它,但我认为我应该提一下。作为对性能敏感的用户的信息,它使用重新渲染。

优点

  • 动画看起来非常漂亮和逼真,弹簧选项也很不错。
  • 交错效果非常好。它也存在于大多数 JS 库中,但这个库是基于最后一次运动创建的,而不是复制最后一次运动,因此有一些不错的运动可能性。
  • 添加onRest 是一件大事。它允许进行以前无法进行的一些排序,因此如果你查看演示,你甚至还没有看到它提供的所有功能。
  • 我目前认为这是与 React 配合得最好的动画工具。

缺点

  • 它不像其他一些库或原生库那样超级即插即用,这意味着你最终会编写更多代码。有些人喜欢这一点,有些人不喜欢。不过,对于初学者来说,它并不友好。
  • 由于代码的复杂性,排序不像一些替代方案那样简单或易读。
  • onRest 还不适用于交错参数。

React 中的 GSAP

GreenSock 提供了如此多的功能,因此它仍然值得在 React 环境中使用。对于更复杂的排序来说尤其如此,因为 React-Motion 没有提供简单的解决方案,而 GreenSock 在这方面表现出色。它需要比平时更多的调整,并且有些在 DOM 中应该工作并且确实工作的东西在 React 中却无法工作。也就是说,我现在已经让 React 和 GSAP 以几种不同的方式良好地配合使用,所以以下是我的做法。

  1. 挂接到原生的 React 组件生命周期方法。
    这是我的做法。当我想让它立即触发时,我使用componentDidMount
  2. 创建一个包含时间线的函数,然后在用于交互的某些内容中调用该函数。我可以使用内联事件处理程序,例如onClick(),并在为其创建的自定义函数中,我将调用另一个函数,该函数在其内部包含一个时间线。在 jQuery 或原生 JS 设置中,我将最初暂停时间线并点击播放,但在这里我不需要这样做。
  3. 这是一篇不错的文章,Chang Wang 在文章中写了如何将它们挂接到ReactTransitionGroup(),这是一种非常酷的做法。
  4. 你可以使用像React-Gsap-Enhancer这样的库。我自己还没有太多使用这个库,但是有一些非常棒的演示。其中一个是基于我自己的一个演示的 fork,我必须说,当我查看代码时,它似乎比我编写的代码冗长得多。我不确定这是由于库还是 React 本身,或者他们的风格。

React 中的 CSS

CSS 动画最近复苏了一些,这可能是因为它是在 React 中进行动画的最简单方法。我喜欢将它们用于一些小东西,例如 UI/UX 交互。如果尝试使用延迟来链接内容,我发现它们的行为有点奇怪。除此之外,它们非常棒,尤其是在进行少量 UI 调整时。在网络上的真实世界动画方面,有时 CSS 就是奥卡姆剃刀。

结论

这是一篇来自一位持续专注于动画工作的作者的观点文章,这些是我在大量使用这些技术后总结出的经验。我的观点可能并不被所有人认同,这没关系。除了作为开发者,考虑到其通用性、性能和易用性之外,我并没有特别偏袒任何技术。希望这些信息能为您节省一些时间。