>웹 프론트엔드 >JS 튜토리얼 >CSS 애니메이션과 JavaScript 애니메이션 비교

CSS 애니메이션과 JavaScript 애니메이션 비교

伊谢尔伦
伊谢尔伦원래의
2017-01-16 16:37:561403검색

CSS3 애니메이션의 장점:

  • 성능이 약간 향상되며, 브라우저는 CSS3 애니메이션에 대해 몇 가지 최적화를 수행합니다(예: 애니메이션을 실행하기 위한 새 레이어 생성)

  • 코드는 비교적 간단합니다

그러나 단점도 분명합니다.

  • 애니메이션 제어에서는 그렇지 않습니다. 유연성이 충분함

  • 호환성이 좋지 않음

일부 애니메이션 기능을 구현할 수 없음(예: 스크롤 애니메이션, 시차 스크롤 등)

JavaScript 애니메이션은 이 두 가지 단점을 보완합니다. 강력한 제어 기능을 갖추고 있으며 단일 프레임을 제어하고 변환할 수 있습니다. 동시에 잘 작성되면 IE6과 완벽하게 호환되고 강력한 기능을 갖습니다. 그러나 CSS 애니메이션의 변환 매트릭스는 C++ 수준 계산이므로 JavaScript 수준 계산보다 빨라야 합니다. 게다가 도서관에 대한 의존도 골치거리이다.

일부 복잡하게 제어되는 애니메이션의 경우 자바스크립트를 사용하는 것이 더 안정적입니다. 몇 가지 작은 대화형 효과를 구현할 때 더 많은 CSS를 고려하세요.

실제 프로젝트 경험에 따르면 같은 맥락에서 두 솔루션의 애니메이션 효율성에는 거의 차이가 없습니다. 효율성에 더 많은 영향을 미치는 것은 다음과 같습니다.

  • 레이아웃을 유발하는지

  • 영역 다시 칠하기

  • 비용이 많이 드는 속성(CSS 섀도우 등)이 있는지

  • 하드웨어 가속 활성화 여부

일반 흐름 요소의 여백과 높이를 동적으로 변경하면 사용하는 것만큼 느린 대규모 레이아웃 프로세스가 발생합니다. JS 또는 CSS3.
요소의translate3D를 동적으로 변경하면 자연스럽게 3D 가속이 활성화됩니다. setTimeout/setInterval/requestAnimationFrame을 사용하는 것과 CSS3을 사용하는 것 사이에는 큰 프레임 속도 차이가 없습니다.

오늘의 주요 차이점은

1. 기능 적용 범위, JS는 CSS3보다 큽니다.

  • 애니메이션 프로세스를 정의하는 @keyframes 재귀적 정의를 지원하지 않습니다. 유사한 애니메이션 프로세스가 여러 개 있고 이를 생성하기 위해 여러 매개변수를 조정해야 하는 경우 중복성이 많이 발생하지만(예: jQuery Mobile의 애니메이션 솔루션) JS는 자연스럽게 세트를 사용하여 여러 기능을 구현할 수 있습니다. 다양한 애니메이션 프로세스

  • 시간 규모에서 @keyframes의 애니메이션 세분성은 거친 반면 JS의 애니메이션 세분성 제어는 매우 미세할 수 있습니다

  • CSS3 애니메이션에서 지원하는 시간 함수가 거의 없고 유연성도 부족합니다

  • 기존 인터페이스로는 CSS3 애니메이션이 2개 이상의 상태 전환을 지원할 수 없습니다

2. 구현/재구성의 난이도는 다양합니다. CSS3는 JS보다 간단하며, 성능 조정 방향이 고정되어 있습니다.

3. , CSS3는 자연스럽게 다운그레이드될 수 있지만 JS는 추가 코드 작성이 필요합니다

4. CSS3에는 호환성 문제가 있지만 JS는 대부분 호환성 문제가 없습니다


다음은 단계별로 진행됩니다. Javascript 기반 DOM 애니메이션 라이브러리(예: Velocity.js 및 GSAP)가 jQuery 및 CSS 기반 애니메이션 라이브러리보다 더 효율적인 이유를 설명합니다.

jQuery

기본부터 시작하겠습니다. Javascript와 jQuery는 혼동될 수 없습니다. Javascript 애니메이션은 빠른 반면 jQuery 애니메이션은 느립니다. 왜? jQuery는 매우 강력하지만 디자인 목표는 효율적인 애니메이션 엔진이 되는 것이 아니기 때문입니다.

  • jQuery는 레이아웃 스래싱을 ​​피할 수 없습니다(어떤 사람들은 이를 "레이아웃 스래싱"으로 번역하기를 좋아합니다. 코드가 애니메이션에만 사용되는 것이 아니라 다른 많은 시나리오에서도 사용되기 때문에 (중복 릴레이아웃/리플로우)가 발생합니다.

  • jQuery는 많은 메모리를 소비하고 종종 가비지 수집을 트리거합니다. 가비지 수집이 실행되면 애니메이션이 멈추기 쉽습니다.

  • jQuery는 reqeustAnimationFrame(RAF) 대신 setInterval을 사용합니다. 왜냐하면 창이 포커스를 잃으면 RAF가 실행을 중지하여 jQuery 버그가 발생하기 때문입니다. (현재 jQuery는 이미 RAF를 사용하고 있습니다.)

레이아웃 스래싱으로 인해 애니메이션이 처음에 정지되고, 가비지 수집이 트리거되면 실행 프로세스 중에 애니메이션이 정지됩니다. RAF를 사용하지 마십시오. 이렇게 하면 애니메이션 프레임 속도가 낮아집니다.

구현 예

레이아웃 스래싱을 ​​방지하려면 DOM에 일괄적으로 액세스하고 업데이트해야 합니다.

var currentTop,
    currentLeft;
/* 有 layout thrashing. */
currentTop = element.style.top; /* 访问 */
element.style.top = currentTop + 1; /* 更新 */
currentLeft = element.style.left; /* 访问 */
element.style.left = currentLeft + 1; /* 更新 */
/* 没有 layout thrashing. */
currentTop = element.style.top; /* 访问 */
currentLeft = element.style.left; /* 访问 */
element.style.top = currentTop + 1; /* 更新 */
element.style.left = currentLeft + 1; /* 更新 */

업데이트 작업 후 액세스 작업을 수행하면 브라우저가 페이지 요소의 스타일을 다시 계산하게 됩니다(올바른 값을 얻으려면 업데이트된 스타일을 적용해야 하기 때문입니다). 이는 일반적인 작업에서는 큰 성능 손실을 일으키지 않지만, 단 16ms 간격으로 애니메이션에 배치하면 상당한 성능 오버헤드가 발생합니다. 작업 순서를 조금만 변경해도 애니메이션 성능이 크게 향상될 수 있습니다.

마찬가지로 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 Transition

  CSS transition 的动画逻辑是由浏览器来执行,所以它的性能能够比 jQuery 动画好。它的优势体现在:

  1. 通过优化 DOM 操作,避免内存消耗来减少卡顿

  2. 使用与 RAF 类似的机制

  3. 强制使用硬件加速 (通过 GPU 来提高动画性能)

  然而实际上Javascript也可以使用这些优化。GSAP 已经做这些优化很久了。Velocity.js 是一个新兴的动画引擎,它不仅仅做了这些优化,甚至走的更远些。我们稍后会谈到这些。

  面对事实,让 Javascript 动画得以媲美 CSS 动画的性能只是我们伟大计划的第一步。第二步才是重头戏,要让 Javascript 动画比 CSS 动画还要快!

  让我们来看看 CSS 动画库的缺陷吧:

  1. Transition 强制使用了 GPU 的硬件加速。导致浏览器一直处于高负荷运转的状态,这反而会让动画变的卡顿。这在移动浏览器上更为严重。(特别要说明的是,当数据在浏览器的主线程和合成线程之间频繁传输的时候特别消耗性能,故容易导致卡顿。某些 CSS 属性,不会受到影响。Adobe 的博客谈到过这个问题。

  2. IE 10以下的浏览器不支持 transition。而目前 IE8 和 IE9 还是很流行的。

  3. transition 不能完全被 Javascript 控制(只能通过 Javascript 来触发 transition),因为浏览器不知道如何同时让 Javascript 控制动画又同时优化动画的性能。

  反过来说: 基于 Javascript 可以决定什么时候启用硬件加速,它可以支持全版本的 IE,并且它完全可以进行批量动画的优化。

Javascript 动画

  所以 Javascript 可以比 CSS transition 性能更好。但是它到底有多块呢?它快到足够可以构建一个3D 动画的demo,通常需要用到 WebGL 才能完成。并且它快到足够搭建一个多媒体小动画,通常需要 Flash 或者 After Effects 才能完成。并且它还快到可以构建一个虚拟世界,通常需要 canvas 才能完成。

  为了更直接的来比较主流动画库的性能,包括 Transit(使用了 CSS transition),让我们打开Velocity的官方文档。

  之前那个问题还在:Javascript 是如何达到高性能的呢?下面是一个列表,列举了基于 Javascript 的动画库能做的事情:

  1. 同步DOM -> 在整个动画链中微调堆栈以达到最小的layout thrashing。

  2. 缓存链式操作中的属性值,这样可以最小化DOM的查询操作(这就是高性能 DOM 动画的阿喀琉斯之踵)

  3. 在同一个跨同层元素的调用中缓存单位转化比率(例如px转换成%、em等等单位)

  4. 忽略那些变动小到根本看不出来的DOM更新

  让我们重新温习下之前学到的关于layout thrashing的知识点。Velocity.js 运用了这些最佳实践,缓存了动画结束时的属性值,在紧接的下一次动画开始时使用。这样可以避免重新查询动画的起始属性值。

$element
    /* Slide the element down into view. */
    .velocity({ opacity: 1, top: "50%" })
    /* After a delay of 1000ms, slide the element out of view. */
    .velocity({ opacity: 0, top: "-50%" }, { delay: 1000 });

在上面的样例中,第二次调用 Velocity 时已经知道了 opacity 的起始值为 1,top 的值为 50%。

  浏览器也可以使用与此类似的优化,但是要做这些事情太过激进,使用场景也会受到限制,开发者就有可能会写出有bug的动画代码。jQuery就是因为这个原因没有使用RAF(如上所说),浏览器永远不会强行实施可能打破规范或者可能偏离期望行为的优化。

  最后,让我们来比较下两个Javascript框架(velocity.js 和 GSAP)。

  • GASP 是一个快速且功能丰富的动画平台。Velocity则更为轻量级,它大大地改善了UI动画性能和工作流程。

  • GSAP 需要付费才能用于商业产品。Velocity 是完全免费的,它使用了自由度极高的 MIT 协议。

  • 性能方面,两者几乎相当,很难区分胜负。

Velocity.js

  之前提到了 GSAP 有着丰富的功能,但这不代表 Velocity 的功能简单。相反的,Velocity 在 zip 压缩之后只有 7kb,它不仅仅实现了 jQuery animate 方法的所有功能,还包含了 颜色、transforms、loop、easings、class 动画和滚动动画等功能。

  简单的说就是 Velocity 包含了 jQuery、 jQuery UI 和 CSS transition 的功能。

  更进一步从易用性的角度来讲,Velocity 使用了 jQuery 的$.queue() 方法,因此可以无缝过渡到 jQuery 的$.animate()、$.fade()和$.delay()方法。并且 Velocity 的语法和$.animate()一摸一样,所以我们根本不需要修改页面的现有代码。

  让我们快速过一下 Velocity.js 的例子:

$element
    .delay(1000)
    /* Use Velocity to animate the element's top property over a duration of 2000ms. */
    .velocity({ top: "50%" }, 2000)
    /* Use a standard jQuery method to fade the element out once Velocity is done animating top. */
    .fadeOut(1000);

  如下是一个高级用法:滚动网页到当前元素并且旋转元素。这样的动画只需要简单的几行代码:

$element
    /* Scroll the browser to the top of this element over a duration of 1000ms. */
    .velocity("scroll", 1000)
    /* Then rotate the element around its Y axis by 360 degrees. */
    .velocity({ rotateY: "360deg" }, 1000);

Velocity 的目标是成为 DOM 动画领域性能最好易用性最高的库。这篇文章主要关注了性能方面。易用性方面可以前往 VelocityJS.org 了解。

请记住一个高性能的 UI 绝不仅仅是选择一个正确的动画库。页面上的其他代码也需要优化。


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.