[css] CSS 키 프레임 애니메이션 CPU 사용량이 높습니다. 이렇게해야합니까?

여러 요소에 다음 키 프레임 애니메이션을 사용합니다.

@keyframes redPulse {
    from { background-color: #bc330d; box-shadow: 0 0 9px #333; }
    50% { background-color: #e33100; box-shadow: 0 0 18px #e33100; }
    to { background-color: #bc330d; box-shadow: 0 0 9px #333; }
}
@-webkit-keyframes redPulse {
    from { background-color: #bc330d; box-shadow: 0 0 9px #333; }
    50% { background-color: #e33100; box-shadow: 0 0 18px #e33100; }
    to { background-color: #bc330d; box-shadow: 0 0 9px #333; }
}
.event_indicator {
    display: inline-block;
    background-color: red;
    width: 5px;
    margin-right: 5px;

    -webkit-animation-name: redPulse;
    -webkit-animation-duration: 1s;
    -webkit-animation-iteration-count: infinite;

    animation-name: redPulse;
    animation-duration: 1s;
    animation-iteration-count: infinite;
}

내 컴퓨터에서 Chrome과 Firefox 모두 CPU 사용량이 약 40 %입니다. 애니메이션의 현재 상태 (좋지만 지금은 사용할 수 없음)입니까? 아니면 마법 속성이 누락 되었습니까?

동일한 애니메이션으로 다음 샘플을 확인할 수 있습니다.
http://jsfiddle.net/Nrp6Q/



답변

예, 페이지에 여러 개의 무한 루프 애니메이션이 있기 때문에 이것은 정상입니다. 따라서 CPU는 이러한 요소가 렌더링되는 동안 지속적으로 작업을 수행합니다. CPU 사용량을 크게 줄이는 “마법”속성이 있습니다.

transform: translateZ(0);

이렇게하면 요소가 자체 레이어로 합성되고 (브라우저가 3D 변환을 수행 할 것이라고 생각하도록 속임으로써) 브라우저는 대부분의 경우 GPU 가속을 활용하여 CPU의 부담을 줄여야합니다. 나를 위해 이것은 약 20 % (거의 절반)까지 줄였습니다.

이 기술에 대한 자세한 내용은 http://ariya.blogspot.com/2011/07/fluid-animation-with-accelerated.html을 참조하십시오.

또한 애니메이션에 키 프레임이 많을수록 더 많은 부담이됩니다. 중간 키 프레임을 잘라낸 상태로 애니메이션을 시도하면 CPU 사용량이 또 다른 상당한 (~ 10-12 %) 감소하는 것을 볼 수 있습니다.

마지막으로, 모든 속성이 동일하지는 않습니다. box-shadow는 브라우저가 배경색보다 매끄럽게 움직이는 것이 훨씬 어렵습니다. 모든 키 프레임은 그대로두고, translateZ (0) 트릭을 사용하여 box-shadow 속성을 삭제하면 CPU 사용량이 10-11 %에 불과했습니다.

이렇게 말하는 것이 고통 스럽지만, 무한 루프 애니메이션의 경우 애니메이션 .gif는 브라우저 애니메이션의 현재 상태에서 CSS3보다 훨씬 더 나은 성능을 발휘할 것입니다. 한동안 페이지.

2017 업데이트 :

여전히이 질문과 답변에 대한 방법을 찾는 사람들에게 , 당신은 설정 과 translate3d(0, 0, 0)동시에 동일한 이점을 제공합니다 . 데모에서 사용 하는 @Farside 의 주석을 무시하십시오. 그러나이 기술을 사용하면 여전히 상당한 차이가 있음을 알 수 있습니다.translateZ(0)translateX()translateY()translate3d(X, Y, Z)translate(X, Y)

이 질문 에 따르면 일부 사람들은 모든 브라우저, 특히 Chrome에서 transform: rotateZ(360deg).


답변

CPU의 부하를 줄일 수있는 가능한 방법 중 하나는 소위를 사용하는 null transform hack것입니다 . 이 방법은 종종 은색 총알 처럼 환영받습니다 . 대부분의 경우 Chrome, Opera 및 Safari와 같은 WebKit 및 Blink 브라우저에서 렌더링 성능을 크게 향상시킵니다.

“Null transform hack”(하드웨어 합성 모드) 사용

널 변환 해킹은 기본적으로 두 가지 작업을 수행합니다.

  1. 하드웨어 합성 모드를 켭니다 (플랫폼에서 지원된다고 가정).
  2. 자체 뒷면 이있는 새 레이어를 만듭니다.

브라우저를 “강제”하려면 다음 CSS 속성 중 하나를 요소에 추가하면됩니다.

transform: translateZ(0);

/* or its friend: */
transform: translate3d(0, 0, 0);

3D 변형으로 작업 할 때 성능을 향상시키기 위해 다음과 같은 속성도 갖는 것이 좋습니다 .

backface-visibility: hidden;
perspective: 1000;

“null transform hack”의주의 사항

많은 객체에 대해 CSS3에서 하드웨어 가속을 활성화하면 성능이 저하 될 수 있습니다!
분명히 각 null 3D 변환은 새 레이어를 만듭니다. 그러나 강제 해킹 레이어 생성이 페이지의 특정 성능 병목 현상에 대한 해결책이 아닐 수도 있습니다. 레이어 생성 기술은 페이지 속도를 높일 수 있지만 비용이 발생합니다. 시스템 RAM과 GPU에서 메모리를 차지합니다. 따라서 GPU가 잘 작동하더라도 많은 객체의 전송이 문제가 될 수 있으므로 GPU 가속을 사용하는 것이 그만한 가치가 없을 수 있습니다. W3C 의 인용 :

그러나 새 레이어에서 요소를 설정하는 것은 비교적 비용이 많이 드는 작업이므로 변환 애니메이션의 시작이 눈에 띄게 1 초 정도 지연 될 수 있습니다.

3D 가속을 사용할 때 많은 작은 항목을 이동하는 것보다 몇 개의 큰 개체를 이동하는 것이 성능이 더 높습니다. 따라서 그것들은 현명하게 사용되어야하며 하드웨어 가속 작업이 페이지의 성능에 실제로 도움이되는지 확인하고 성능 병목 현상이 페이지의 다른 작업으로 인해 발생하지 않는지 확인해야합니다.

또한 GPU는 복잡한 수학적 / 기하학적 계산을 수행하기 위해 특별히 설계되었으며 GPU에 대한 작업을 오프 로딩 하면 엄청난 전력 소비가 발생할 수 있습니다 . 분명히 하드웨어가 작동하면 대상 장치의 배터리도 작동합니다.

현대적인 방법 : will-change재산

진전은 한곳에 서 있지 않습니다 … W3C는 will-changeCSS 속성을 도입 했습니다. 간단히 말해서이 will-change속성을 사용하면 요소에 적용 할 수있는 변경 사항의 종류를 미리 브라우저에 알릴 수 있으므로 필요하기 전에 적절한 최적화를 설정할 수 있습니다.

초안 에서 그들이 말하는 내용은 다음과 같습니다 .

will-change이있어 필요할 때 전에 UA가 시간이 적절한 최적화를 설정할 수 있도록이 사양에 정의 된 속성은, 저자가 앞서-의 시간 속성이 미래의 변화 가능성이 무엇을 선언 할 수 있습니다. 이렇게하면 실제 변경이 발생하면 페이지가 빠르게 업데이트됩니다.

를 사용 will-change하여 브라우저에 다가오는 변환에 대해 암시하는 것은 변환 될 것으로 예상되는 요소에이 규칙을 추가하는 것만 큼 간단 할 수 있습니다.

will-change: transform;

모바일 용으로 개발할 때 개발자는 모바일 웹 앱을 작성하는 동안 다양한 장치 제약 조건을 고려해야합니다. 브라우저는 점점 더 스마트 해지고 있으며, 때로는 가속을 겹치거나 해키 방식으로 동작을 강제하는 대신 결정을 플랫폼 자체에 맡기는 것이 좋습니다.


답변

CSS3로 일부 요소를 애니메이션 할 때 CPU 사용량이 높은 비슷한 경우가있었습니다. 전체 페이지에 사용 된 불투명도 및 그림자 속성을 사용하여 ~ 7 개 요소의 “왼쪽”속성에 애니메이션을 적용했습니다. 슬프게도 성능이 전혀 향상되지 않은 jQuery.animate로 전환하기로 결정했습니다. 페이지를 표시하는 동안 내 CPU (i7)는 여전히 ~ 9-15 % 였고, 몇 가지 트릭 (translateZ 등)도 실제로 성능을 향상시키지 못했습니다. 내 레이아웃이 엉망이되는 동안 (일부 절대 위치 요소가 포함되었습니다. !).

그런 다음이 멋진 확장 기능을 발견했습니다. http://playground.benbarnett.net/jquery-animate-enhanced/

나는 단순히 .js 파일을 참조하고 jQuery 전환에서 단일 변경을 수행하지 않았으며 내 CPU 사용량은 이제 동일한 페이지에서 1-2 %입니다.

내 추천 : CSS3 전환을 사용하여 CPU 문제에 직면 할 때 jQuery + animate-enhanced-plugin으로 전환하십시오.


답변

CPU 대신 GPU를 사용하려는 다음 클래스 요소에서 이것을 사용할 수도 있습니다.

.no-cpu {
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
    -ms-transform: translateZ(0);
}

<element class="event_indicator no-cpu">animation...</element >


답변

여기에보고 된 ‘펄싱’배경 애니메이션의 특정 사례에 대해 저는 css + js 솔루션을 생각해 냈습니다.

제 경우에는 배경 애니메이션이 배경색이 아닌 배경 위치 속성에 있었지만 원리는 동일합니다.

예, 특정 배경을 가진 블록이 있다고 가정 해 보겠습니다.

<div class="nice-block">...</div>

스타일 지정 : (scss)

.nice-block {
  background-color: red;
  //or it can be: background: linear-gradient(45deg, #red, #white, #red);
  //and:          background-size: 600% 600%;

  //the transform and will-change properties
  //are here to only enable GPU
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  -ms-transform: translateZ(0);
  will-change: transform;

  transition: background-color 5s ease;
  //if you want to add a pulsing effect 
  //to a gradient, see the following two lines:
  // background-position: 0% 50%!important;
  // transition: background-position 5s ease;

  &.animated {
    background-color: white;
    //and in case of gradient animation:
    // background-position: 100% 50%!important;
  }
}

이제 JavaScript를 사용하여 블록에 ‘animated’클래스를 추가하여 효과를 만들 차례입니다.

var bgAnimateTimer;
function animateBg () {
  clearTimeout(bgAnimateTimer);
  bgAnimateTimer = setTimeout(function () {
    clearTimeout(bgAnimateTimer);
    bgAnimateTimer = setTimeout(function () {

      document.querySelector('.nice-block').classList.toggle('animated');

      //jQuery alternative is:
      // $('.nice-block').toggleClass('animated');

      animateBg ();
    }, 5000); //5 seconds for the animation effect
  }, 2500); //2.5 seconds between each animation
}

animateBg ();

이것은 제 경우의 성능을 ~ 15 배 향상 시켰습니다.

(i) 5 초와 다른 값을 원하는 경우 css 및 js에서 전환 및 시간 초과에 대한 초를 올바르게 계산합니다.


답변