深入探究使JavaScript动画流畅的一些方法

基于Javascript的动画暗中同CSS过渡效果一样,甚至更加快,这怎么可能呢?而Adobe和Google持续发布的富媒体移动网站的性能可媲美本地应用,这又怎么可能呢?

本文逐一遍览了基于Javascript的DOM动画库,如Velocity.js和GSAP,看其是如何比jQuery和CSS动画效果更具性能的.
jQuery

让我们先从基础的开始: JavaScript 和 jQuery 被错误的混为一谈了. JavaScript 动画是很快的. jQuery 把它放慢了下来。为什么?因为 — 尽管jQuery非常强大 — 但成为一个性能强劲的动画引擎从来都不是jQuery的设计目标:

    jQuery 不能避免 布局颠簸 ,这得归因于它的代码库提供了动画之外的多种用途.

    jQuery 的内存消耗经常会触发垃圾回收,那样会 时不时的让动画定格下来.

    jQuery 使用 setInterval 而不是 requestAnimationFrame (RAF) 来 保护新技术不受其自身的影响.

应该注意到布局颠簸就是在动画开始部分的不顺畅,垃圾回收就是造成动画期间不顺畅的元凶, 而没有使用RAF则会导致低帧率.

实现示例

避免造成布局颠簸的DOM查询和更新组合:
 

var currentTop, currentLeft; /* With layout thrashing. */ currentTop = element.style.top; /* QUERY */ element.style.top = currentTop + 1; /* UPDATE */ currentLeft = element.style.left; /* QUERY */ element.style.left = currentLeft + 1; /* UPDATE */ /* Without layout thrashing. */ currentTop = element.style.top; /* QUERY */ currentLeft = element.style.left; /* QUERY */ element.style.top = currentTop + 1; /* UPDATE */ element.style.left = currentLeft + 1; /* UPDATE */

发生在更新之后的查询会强制浏览器对页面的计算式数据进行重新计算 (同时会把新的更新效果考虑在内). 这样就会对动画产生显著的开销,而这只是16毫秒微小间隔的运行超时.

类似的,实现 RAF 并不必须是对你的现有代码库的显著返工. 让我们拿RAF的基础实现同setInterval比较一下:
 

var startingTop = 0; /* setInterval: Runs every 16ms to achieve 60fps (1000ms/60 ~= 16ms). */ setInterval(function() { /* Since this ticks 60 times a second, we divide the top property's increment of 1 unit per 1 second by 60. */ element.style.top = (startingTop += 1/60); }, 16); /* requestAnimationFrame: Attempts to run at 60fps based on whether the browser is in an optimal state. */ function tick () { element.style.top = (startingTop += 1/60); } window.requestAnimationFrame(tick);

RAF 产生了推动动画性能的最大可能性,你可以对你的代码进行单一的变更.

CSS 转换

CSS转换通过把动画逻辑甩给浏览器本身去处理而超越了jQuery,这在以下几方面是有效果的:(1)优化DOM交互和内存消耗以避免卡顿(颠簸),(2)利用引擎的RAF原则,(3)强制硬件加速(利用GPU的能力来提高动画性能)。

然而,现实是,这些优化也可以在JavaScript中直接执行。GSAP已经这样做了多年。Velocity.js,一个新的动画引擎,不仅利用了同样的技术,而且还向前多走了几步——我们不久会探讨这些。

面对事实,JavaScript动画可以与CSS转换竞争只是我们康复计划的第一步。第二步是实现“JavaScript动画实际上可以比CSS转换更快”。


现在我们开始谈谈CSS变换的弱点:

相反的,基于JavaScript的动画库则可以自行确定合适开启硬件。它们原生支持各版本IE浏览器,并且它们尤其适合批量动画优化。

我的建议是仅当你单独为移动端开发且仅实现简单动画时使用原生CSS变换。这种环境下,transition是一种原生有效的解决方案,可以使你在样式表中实现所有动画逻辑,而不用添加额外的JavaScript库,从而避免你的页面变得臃肿。然而,当你在设计复杂的UI,或者是开发存在不同状态的UI的App时,你就应该使用动画库以使动画保持流畅,同时使工作流程易于管理。Transit是一个在管理CSS变换方面做得尤其优秀的库。

JavaScript 动画

好了,那JavaScript可就在性能方面占据上风了. 但Javascript究竟具体快了多少呢? 好吧 — 最初 — 对于构建一个实在的 3D动画示例 是足够快的,通常在构建中你只会看到有使用WebGL. 而构建一个 多媒体小动画 也够了,通常你看到只会使用Flash或者After Effects构建. 而构建一个 虚拟世界 也够了,通常你只会看到使用canvas构建.

为了对领先的动画库,当然还要包含Transit(它使用CSS渐变效果),进行直接的对比, 回头去看看Velocity在VelocityJS.org上的文档.

问题仍然是: JavaScript是怎样具体的达成其高水平性能的? 下面是对基于Javascript动画能够被执行这一目标的优化的一个简短清单:

    同步 DOM → 在整个动画链中间入栈以最小化布局抖动.

    为整个链式调用缓存属性值,以最小化DOM查询发生 (这些就是高性能DOM动画的坑).

    在同样的调用中缓存整个同级别元素的单元转换率 (比如 px 到 %, em, 等等.).

    当更新可能会在视觉上不可见时跳过样式更新.

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgdjwf.html