动画性能的故事

Avatar of Chris Coyier
Chris Coyier 发布

DigitalOcean 为您的旅程的每个阶段提供云产品。从 200 美元的免费积分 开始!

一切从一条推特开始

上下文

所以我们都在同一页上,Hugo 的意思是,有两种不同的方式可以“移动”元素。

  • 为元素设置 relativeabsolutefixed 定位。然后,您可以使用 toprightleftbottom(或任何组合)来移动物体。
  • 确保元素具有 display 值为 blockinline-block,然后使用 transform 值 translate()translateX()translateY() 来移动元素。

“更好”,版本 1

我对这个语境下“更好”含义的第一个想法是,哪种方式在不同情况下更合适。这让我说:“不要将定位与设计动效混淆。”

举个例子。你有一个按钮。你想对这个按钮应用一个效果,让它在 :active 状态下向下移动 2 像素,模拟“按下”的效果。这是一种设计动效,应该用 translate() 来完成。你也可以用 topbottom 和相对定位来实现,但这样就会混淆定位和设计动效的概念。

假设在应用程序的另一个地方,你绝对定位了一个按钮(完全合法)。现在,当 top: 2px; 被应用到按钮的 :active 状态时,这个按钮可能会飞到你意想不到的地方,可能导致按钮无法点击。

使用 translate() 将始终从元素的当前位置“推动”它,这对于这种效果,或者任何设计特定的动效来说都是完美的。

“更好”,版本 2

Hugo 更可能指的是性能。使用 translate() 来移动元素比使用 top/right/bottom/left 具有更好的性能,这已经成为一种通用的建议。但是,数据是否支持这种说法?让我们来看看。

首先,我做了一个非常简单的动画,一个红色球来回移动。

在我的肉眼看来,在最新稳定的 Chrome (23) 和装有 RAM 的 Retina MacBook Pro 上,translate() 版本确实略微表现更好。我可以看到 top/left 版本有非常轻微的卡顿。感知很重要,但让我们看看真实的数据。

在 Chrome 开发者工具中,您可以点击“Timeline”选项卡,然后点击“Frames”,然后按下底部的圆形“Record”按钮。在动画运行时,开始录制一小段时间,然后停止它。如果其他网站不可见,特别是如果它们正在进行任何动画,数据会更好。

在 top/left 版本中,您可以看到偶尔的峰值出现在标有“60 FPS”的线之上,即每秒六十帧。这是我们试图保持在下面的线,因为它相当于完美的平滑感知运动。

高于线 == 卡顿。
流畅

但是等等

这变得更加复杂。我开始与 Paul Irish 交谈,他是 Google Chrome 团队的成员。Paul 认为,由于这些“绘制”非常简单,这可能不是最佳的真实性能指标。Paul 采用了我的演示,并提高了复杂性。不是红色球,Josh Hibberts MacBook Pro。不是白色背景,Nate Eagle 的沙发布料

Paul 的例子显示出与我们预期相反的结果时,事情变得奇怪了。top/left 版本看起来比 translate() 版本更平滑。令人惊讶的是,“Frames”时间轴没有显示任何重大差异。

这就是 Paul 开始深入研究这个奇怪的世界的地方。他想出了很多有趣的东西!Paul 与 Chrome 团队中的另一位 Paul,Paul Lewis 交谈,他同意“使用 translate() 来进行设计动效更明智”。但接着说,这不仅仅是帧速率的问题。使用 translate(),你可以获得亚像素动画,这是一种在像素之间模糊的效果,通常会导致更平滑的动画。

在亚像素 [动画] 中,你会失去清晰度,这是正确的。关键是在极值处保持更长的圆形值,这样你的眼睛就能获得清晰度的满足,同时获得运动的平滑性。

Paul Irish 深入挖掘

我会把这个交给 Paul。 他制作了一个 13 分钟的视频,你应该看看。它解释了所有这些花哨的 GPU 东西、亚像素渲染等等。