CSS анімація ключових кадрів Використання процесора дуже велике, чи слід так?


78

Я використовую наступну анімацію ключових кадрів для кількох елементів:

@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;
}

На своєму комп’ютері я отримую близько 40% використання процесора як у Chrome, так і у Firefox. Це поточний стан анімації (приємний, але поки що не придатний для використання) чи мені не вистачає якоїсь магічної властивості?

Ви можете перевірити наступний зразок з тією ж анімацією: http://jsfiddle.net/Nrp6Q/


1
На додаток до високого процесора, у моєму випадку це також, здається, пов'язано з постійно зростаючим обсягом пам'яті на основі диспетчера завдань Chrome.
Кевін Буллахі

@KevinBullaughey, мабуть, кожен об’єкт має свою ціну: вони займають пам’ять в системній оперативній пам’яті та / або на графічному процесорі, див . Пояснення , плюс сама анімація - відносно дорога операція!
Farside

2
не анімуйте поле-тінь. замість цього перемістіть властивість box-shadow до псевдоелемента та анімуйте його непрозорість і перетворіть властивості
Денис

@Denis move box-shadow property to pseudoelement and animate it's opacity and transform propertiesЯ знаю, що питання про операційну програму досить давнє, але чи можете ви навести приклад чи посилання?
tonix

Відповіді:


90

Так, це нормально, оскільки у вас на сторінці є кілька анімацій з нескінченним циклом. Тому центральний процесор постійно виконує роботу, поки ці елементи відображаються. Існує "чарівна" властивість, яка значно зменшить використання центрального процесора, а саме:

transform: translateZ(0);

Це скомпонує елементи у власні шари (обманувши браузер, що він буде робити 3D-перетворення), і браузер, у більшості випадків, повинен скористатися прискоренням графічного процесора, зменшуючи навантаження на центральний процесор. Для мене це скоротило його приблизно на 20% (майже наполовину).

Щоб прочитати більше про цю техніку, подивіться на: http://ariya.blogspot.com/2011/07/fluid-animation-with-accelerated.html

До того ж, чим більше ключових кадрів у вас в анімації, тим більше вона також буде оподатковуватися. Просто спробуйте анімацію з вирізаним середнім ключовим кадром, і ви побачите ще одне істотне (~ 10-12%) падіння використання центрального процесора.

Нарешті, не всі властивості однакові - браузеру набагато важче плавно анімувати, ніж, скажімо, фоновий колір. Залишивши всі ключові кадри недоторканими, але відкинувши властивість box-shadow, використовуючи фокус translateZ (0), використання мого центрального процесора коливалося лише на 10-11%.

Як би мені не було болісно це говорити, для анімації з нескінченним циклом анімований файл .gif буде виконувати набагато краще, ніж CSS3, у поточному стані анімації браузера, особливо якщо ви плануєте, щоб багато з них залишалися відображатими на сторінку протягом деякого часу.

Оновлення 2017:

Для тих, хто все ще знаходить свій шлях до цього запитання та відповіді, translate3d(0, 0, 0)надається така ж перевага, як translateZ(0)і ви, що ви просто налаштовуєте translateX()і translateY()одночасно. Будь ласка, проігноруйте коментар @Farside, оскільки він використовує translate3d(X, Y, Z)у своїй демонстрації, але не порівнює його з таким translate(X, Y), що свідчить про те, що використання цієї техніки все одно суттєво впливає .

Відповідно до цього питання , деякі люди знайшли кращу продуктивність у всіх браузерах, особливо в Chrome, з transform: rotateZ(360deg).


3
Ні, це вже не має ніякої різниці , спробував у Firefox 45.0.2 та спробував у Chrome 50.0.2661. Я думаю, що він застосовує GPU якомога більше навіть без фальшивих перетворень translateZ(0). Мені здається, CSS-анімацію зараз погано використовувати, оскільки з простими анімаціями тривіального квадрата вона сильно нагріває процесор.
Farside

1
Чому голосувати проти, коли ваші висновки відповідають тому, що я писав вище? У цьому прикладі у вас запущений нескінченний цикл - використання мого центрального процесора становить від 10 до 14%. Ви використовували translate3d, що є тим же самим, що і translatez (0) - коли ви видаляєте, що використання процесора зростає. Це, безумовно, все ще має значення.
skyline3000

4
@Farside, будь ласка, розгляньте можливість редагування чи видалення Вашого коментаря, оскільки це остаточно неправильно та дає дезінформацію. Ваша демонстрація не порівнює анімацію з і без translateZ(0), вона лише показує translate3d(x, y, z). Якщо порівняти це із справедливим translate(x, y), ви побачите суттєву різницю, яку цей метод все ще робить.
skyline3000

1
Дякую! Зменшує завантаження процесора з 170% (!) До 13%. Ого.
Zack Katz

1
@ skyline3000 Здається, метод translateZ не покращує продуктивність macOS. Ось мій приклад stackoverflow.com/questions/47296808/…
Вінстон,

17

Одним із можливих способів зменшити навантаження на центральний процесор є використання так званого null transform hack, який часто називають щось на зразок срібної кулі . У багатьох випадках це суттєво покращить ефективність візуалізації у веб-переглядачах WebKit та Blink, таких як Chrome, Opera та Safari.

Використання "зламу нульового перетворення" (апаратний режим композитування)

Хак нульового перетворення в основному робить дві речі:

  1. Він вмикає апаратний режим композитування (за умови, що він підтримується для платформи)
  2. Він створює новий шар із власною опорною поверхнею

Щоб "примусити" браузер, просто додайте до елемента одну з цих властивостей CSS:

transform: translateZ(0);

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

Під час роботи з 3D-перетвореннями добре мати такі властивості, щоб покращити продуктивність :

backface-visibility: hidden;
perspective: 1000;

Застереження "нульового перетворення хака"

Увімкнення апаратного прискорення в CSS3 для багатьох об’єктів може сповільнити продуктивність! Очевидно, кожне нульове 3D-перетворення створює новий шар. Однак створення шару з примусовим злому не завжди може бути рішенням певних вузьких місць продуктивності на сторінці. Методи створення шарів можуть підвищити швидкість сторінки, але вони мають свою вартість: вони займають пам’ять в системній оперативній пам’яті та на графічному процесорі. Отже, навіть якщо графічний процесор робить хорошу роботу, передача багатьох об’єктів може бути проблемою, так що використання прискорення графічного процесора може не коштувати того. Цитата з W3C :

Однак налаштування елемента у свіжому шарі є відносно дорогою операцією, яка може затримати початок анімації перетворення на помітну частку секунди.

Переміщення кількох великих об'єктів має вищу ефективність, ніж переміщення великої кількості дрібних предметів при використанні 3D-прискорення. Отже, ними потрібно грамотно користуватися, і вам потрібно переконатися, що апаратне прискорення вашої операції дійсно сприятиме підвищенню продуктивності вашої сторінки, а також, що вузьке місце продуктивності не спричинене іншою операцією на вашій сторінці.

Більше того, графічний процесор розроблений спеціально для виконання складних математичних / геометричних розрахунків, і операції розвантаження на графічний процесор можуть забезпечити значне споживання енергії . Очевидно, що коли апаратне забезпечення спрацьовує, це робить і акумулятор цільового пристрою.

Сучасний спосіб: will-changeвласність

Прогрес не стоїть на одному місці ... W3C представив will-changeвластивість CSS. Якщо коротко, will-changeвластивість дозволяє заздалегідь повідомити браузер про те, які зміни ви, можливо, внесете в елемент, щоб він міг налаштувати відповідні оптимізації до того, як вони знадобляться.

Ось що вони говорять у проекті :

will-changeВластивість , певне в даному описі , дозволяє автору оголосити вперед-Несвоєчасне , які властивості можуть змінитися в майбутньому, тому UA може встановити відповідні оптимізації деякий час , перш ніж вони необхідні. Таким чином, коли відбувається фактична зміна, сторінка швидко оновлюється.

Використовуючи will-changeнатяк на браузер про майбутню трансформацію, можна настільки просто, як додати це правило до елемента, який ви очікуєте перетворити:

will-change: transform;

Розробляючи для мобільних пристроїв, розробники змушені враховувати широкий спектр обмежень пристроїв під час написання мобільних веб-програм. Браузери стають розумнішими, і іноді краще залишити рішення на самій платформі, замість того, щоб перекривати прискорення і змушувати поведінку хакерським чином.


На сторінці MDN сказано: "Не застосовувати зміну волі до забагато елементів". та "Використовуйте економно". Під капотом, поточні реалізації цієї властивості браузера, здебільшого, все ще просто складають елементи. Ця функція не тільки нестандартна (це все ще робочий проект), але також явно не той підхід "срібної кулі", яким ви її видаєте. Крім того, ваша відповідь насправді нічого не пояснює про використання процесора операційної системи, а також не показує порівняння використання центрального процесора.
skyline3000

2
@ skyline3000, я писав плюси, мінуси та застереження. Читайте уважніше, will-change- це не моя рекомендація, але це більш витончений і сучасний спосіб "натякати браузеру на майбутнє перетворення" , а не примушувати його. "вітається як щось срібна куля" - належить так званому null transform hack, а не will-changeмайну, як ви заявляєте. Мені добре з вашим голосом проти, я розумію, що ви можете боятися конкуренції;)
Farside

4

У мене був подібний випадок високого використання центрального процесора під час анімації деяких елементів за допомогою CSS3. Я анімував "ліву" властивість ~ 7 елементів, з деякими властивостями непрозорості та тіні, використовуваними на всій моїй сторінці. Я вирішив перейти на jQuery.animate, що, на жаль, зовсім не покращило продуктивність. Мій центральний процесор (i7) все ще знаходився на рівні ~ 9-15% під час відображення сторінки, кілька хитрощів (translateZ тощо) насправді також не покращили продуктивність - при цьому мій макет був зіпсований (були задіяні деякі елементи з абсолютним розташуванням, ну !).

Потім я натрапив на це чудове розширення: http://playground.benbarnett.net/jquery-animate-enhanced/

Я просто посилався на .js-файл, не зробив жодної зміни при переходах jQuery, і моє використання ЦП зараз становить 1-2% на тій самій сторінці.

Моя рекомендація: стикаючись із проблемами центрального процесора за допомогою переходів CSS3, перейдіть на jQuery + плагін animate-advanced-plugin.


1
У більшості випадків багато проектів не містять jquery як залежність, тому імпорт додаткового пакета може бути неприйнятним.
Dimitris Filippou

3

Ви також можете використовувати це на будь-якому з наступних елементів класу, де ви хочете використовувати GPU замість CPU

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

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

1
ви забули "зміни волі", а також вам слід перейменувати його на "force-gpu", тому що "no-cpu" є дуже неточним і дуже оманливим.

1

До окремого випадку "пульсуючої" фонової анімації, про який я повідомляю тут, я придумав рішення css + js.

У моєму випадку фонова анімація була скоріше властивістю background-position, а не кольором фону, але принцип той самий.

Добре, припустимо, у вас є блок із певним фоном:

<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:

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) Примітка: правильно обчислювати секунди для переходу та тайм-ауту як у css, так і в js, якщо ви хочете, щоб значення відрізнялися від 5 секунд.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.