FLIP技术让动画更流畅 - 掘金

FLIP Your Animations

拯救动画卡顿之 FLIP

为什么使用FLIP

作为一名前端开发者,项目中我们会经常实现一些动画效果,这些动画通过设置heightwidthtopleft或者除了transformopacity其他的属性值来完成。您可能已经注意到,这些动画技术已经有些过时,这其实是有原因的。当任何触发布局更改的属性(比如height)变化时,浏览器都必须检查其他元素的布局是否发生了改变,这代价是很昂贵的 浏览器的回流与重绘 (Reflow & Repaint)。如果计算所花费的时间超过了一个动画帧(大约16.7毫秒),则该动画帧将被跳过,因为该帧没有及时渲染,所以页面有时会出现卡顿的情况。在保罗·刘易斯(Paul Lewis)的文章Pixels are Expensive,他深入探讨了如何渲染像素以及各种性能支出。

简而言之,项目开发过程中,我们要尽量减少一些必要样式修改所导致的浏览器回流操作。FLIP技术可以很好的帮助我们如何仅使用transformopacity来模拟一些常见的布局修改动画。

FLIP 什么是

在css动画中,除了 transform 和 opacity 之外的动画开销都比较大(包括left、top等定位元素),动画会有一点迟滞,因为浏览器必须递归检查其他元素的布局是否因此而改变。

所以Flip就是一个仅仅通过transform这个属性来实现流畅无延时的动画的技术。

FLIP 的实现原理

简单来说,FLIP就是记录一个元素变化前和变化后的状态,然后通过JS模拟重播这一动画的过程。

FLIP 是 First, Last, Invert, Play 的缩写,最早由 Paul Lewis 提出

以下是如何使用Web Animations API实施这些步骤:

https://codepen.io/davidkpiano/pen/EbwrQQ

FLIP 适合用在什么地方

为什么要用倒置,而不是通过加transform直接从开始到结束

对性能的影响

从交互结束到感知到响应大概需要 100ms 的生理反应时间,如果网站能在这 100ms 内做出响应,那么对用户来说就相当于网站立即进行了响应,然后只需要保证动画在 60FPS 运行就能给用户带来最佳的体验。

我们可以充分利用用户 100ms 生理反应时间来进行相关的计算:getBoundingClientRect 或 getComputedStyle,并通过 FLIP 技术使动画尽快开始,最后通过 transform 和 opacity 的动画来保证动画的平滑运行。

FLIP 技术带来的改变对于 PC 端可能并不是那么明显,但对于 CPU 并不算非常强大的移动端却是相当显著。

Transform 和 Opacity

我们可以通过工具,例如 CSS Triggers 来查看哪些属性会在动画时触发重绘。在工具中,查看 transform 的相关内容,你将看到:

非常好的是,更改 transform 不会触发任何几何形状变化或绘制。这意味着该操作可能是由合成器线程在 GPU 的帮助下执行。

opacity 属性的行为也类似。因此,他们是在 web 上做元素移动的理想选择。

硬件加速

诸如 perspectivebackface-visibility 和 transform:translateZ(x) 等 property 将让浏览器知道你需要硬件加速。

如果要对一个元素进行硬件加速,可以应用以下任何一个 property (并不是需要全部,任意一个就可以)

perspective: 1000px;
backface-visibility: hidden;
transform: translateZ(0);

许多像 GreenSock 这样的 JS 库都会默认你需要硬件加速,并在默认情况下应用,所以你不需要手动设置它们。

Timing

对于简单 UI 过渡,即从一个状态到另一个没有中间状态的状态,通常使用 0.1s 到 0.4s 之间的计时,大多数人发现 0.25s 是一个最佳选择。你能用这个定时做任何事情吗?并不是。如果你有一些元素需要移动更大的距离,或者有更多的步骤或状态变化,0.25s 并不会有很好的效果,你将不得不有更多的目的性,而且定时也需要更加独特。但这并不意味着你不能在应用中重复使用效果好的默认值。

你也可能会发现,起始动画比结束动画的时间稍长一些,看起来会更好一些。用户通常是在动画开始时被引导的,而在动画结束时没有那么多耐心,因为他们想继续他们的动作。

DEMO

FLIP原理实践

https://codepen.io/wzc570738205/pen/VwaNmxg?editors=1010

官方 FLIP.js 实践

https://codepen.io/MrLeo/pen/NWRyWpg

https://codepen.io/MrLeo/pen/YzGezjq

Flipping.js : 通过向 data-flip-key="..." HTML元素添加属性,可以可预测和有效地跟踪可能因状态而异的位置和尺寸的元素