CSS анимация перегружает процессор

У меня есть анимация и JS для чередования 2-х делителей и изменения их фоновых изображений (из массива из нескольких десятков изображений), что-то вроде взаимозаменяемых делений. Все работает просто отлично, однако при запуске анимации я вижу, что мой процессор работает на 100%. Сначала я подумал, что это может быть связано с setInterval, однако, когда я изменил код с чередования изображений, чтобы просто увеличить число с каждой итерацией и записать его в консоль - я увидел резкое снижение перегрузки процессора, примерно на 40-50%. Так что я понял, что это может быть связано с анимацией.

Вот мой HTML-код:

<div class="wallpaper wallpaper-1" id="wallpaper-1"></div>
<div class="wallpaper wallpaper-2" id="wallpaper-2"></div>

CSS:

.wallpaper {
    width: 100%;
    height: 100%;
    position: absolute;
    opacity: 0;
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
    -webkit-transform: translateZ(0);
    -webkit-animation-timing-function: linear;
}

.animate {
    -webkit-animation-name: fadeInOut;
    -webkit-animation-duration: 6s;
}

@-webkit-keyframes fadeInOut {
    0% {
        opacity: 0;
        -webkit-transform: scale(1);
    }
    16% {
        opacity: 1;
    }
    90% {
        opacity: 1;
    }
    100% {
        opacity: 0;
        -webkit-transform: scale(1.1);
    }
}

И JS, который делает все это галочкой:

Wallpapers.get().then(function(list) {
    var wp1, wp2, divs = [], path, bgs = [], counterBgs = 0, bgsLength, currentId, doInterval;
    wp1 = document.getElementById('wallpaper-1');
    wp2 = document.getElementById('wallpaper-2');
    divs = [ wp1, wp2 ];
    path = 'assets/img/wallpapers/';
    bgs = list.data;
    bgsLength = bgs.length;

    //Preload images
    for(var i = 0; i < bgsLength-1; i++) {
        var wp = new Image();
        wp.src = path+list.data[i];
    }

    function manageBg() {
        setInterval(function(){
            doInterval();
        }, 4000);
    }

    doInterval = function doInterval() {
        currentId = counterBgs % bgsLength;
        if (counterBgs % 2 === 0) {
            wp1.style.backgroundImage = "url(" + path + bgs[currentId] + ")";
            wp1.classList.add('animate');
            wp1.style.zIndex = 1;
            wp2.style.zIndex = 0;
            setTimeout(function() {
                wp1.classList.remove('animate');
            }, 5950);
        } else {
            wp2.style.backgroundImage = "url(" + path + bgs[currentId] + ")";
            wp2.classList.add('animate');
            wp1.style.zIndex = 0;
            wp2.style.zIndex = 1;
            setTimeout(function() {
                wp2.classList.remove('animate');
            }, 5950);
        }
        counterBgs++;
    };
    doInterval();
    manageBg();
});

Есть идеи, как уменьшить перегрузку процессора?

1 ответ

Ответ будет изменением свойства CSS.

will-change - это свойство, которое оптимизирует анимацию, сообщая браузеру, какие свойства и элементы должны быть изменены, что потенциально повышает производительность этой конкретной операции.

Источник статьи: will-change - css tricks

Свойство will-change будет использовать аппаратное ускорение, чтобы снизить нагрузку на ваш процессор и выделить анимацию / преобразование CSS3 для графического процессора.

Старый: translateZ() или же translate3d() мотыга

В течение достаточно долгого времени мы использовали так называемый взлом translateZ() (или translate3d()) (иногда также называемый взломом нулевого преобразования), чтобы обмануть браузер, заставляя нашу анимацию двигаться и превращаться в аппаратное ускорение. Мы делаем это, добавляя простое трехмерное преобразование к элементу, который не будет преобразовываться в трехмерном пространстве. Например, элемент, который анимирован в двумерном пространстве, может быть аппаратно ускорен путем добавления к нему простого правила:

transform: translate3d(0, 0, 0);

Аппаратное ускорение операции приводит к созданию так называемого слоя композитора, который загружается в GPU и комбинируется с ним. Однако создание слоя принудительного взлома не всегда может быть решением некоторых узких мест производительности на странице. Методы создания слоев могут повысить скорость страницы, но они сопряжены с затратами: они занимают память в системной памяти и на графическом процессоре (особенно ограничено на мобильных устройствах), и их наличие может иметь плохие последствия (особенно на мобильных устройствах), поэтому они должны использоваться с умом, и вы должны убедиться, что аппаратное ускорение вашей работы действительно поможет производительности вашей страницы, и что узкое место в производительности не вызвано другой операцией на вашей странице.

Чтобы избежать взломов создания слоя, было введено новое свойство CSS, которое позволяет нам заблаговременно информировать браузер о том, какие изменения мы можем внести в элемент, тем самым позволяя ему оптимизировать работу с ним. Элемент заблаговременно выполняет потенциально дорогостоящую работу по подготовке к такой операции, как анимация, например, перед тем, как анимация фактически начинается. Это свойство является новым свойством изменения воли.

Новое: Великолепная воля изменит собственность

Свойство will-change позволяет заблаговременно информировать браузер о том, какие изменения вы можете внести в элемент, чтобы он мог настроить соответствующие оптимизации до того, как они понадобятся, что позволяет избежать нетривиального запуска стоимость, которая может негативно повлиять на отзывчивость страницы. Элементы могут быть изменены и отображены быстрее, и страница сможет обновляться быстро, что приведет к более плавному восприятию.

Например, при использовании CSS 3D-преобразований для элемента элемент и его содержимое могут быть переведены в слой, как мы упоминали ранее, до того, как они будут объединены (выведены на экран) позже. Однако установка элемента в новом слое является относительно дорогой операцией, которая может задержать начало анимации преобразования на заметную долю секунды, вызывая это заметное "мерцание".

Чтобы избежать этой задержки, вы можете сообщить браузеру об изменениях за некоторое время до того, как они действительно произойдут. Таким образом, у него будет некоторое время для подготовки к этим изменениям, так что, когда эти изменения произойдут, слой элемента будет готов и анимация преобразования может быть выполнена, а затем элемент может быть визуализирован и страница обновлена ​​быстро.

Используя will-change, намекнуть браузеру о предстоящем преобразовании можно так же просто, как добавить это правило к элементу, который вы ожидаете преобразовать:

will-change: transform;

Вы также можете объявить браузеру о своем намерении изменить позицию прокрутки элемента (положение элемента в видимом окне прокрутки и его видимую часть в этом окне), его содержимое или одно или несколько значений его свойств CSS, указав название свойств, которые вы ожидаете изменить. Если вы ожидаете или планируете изменить несколько значений / аспектов элемента, вы можете предоставить список значений через запятую. Например, если вы ожидаете, что элемент будет анимирован и перемещен (его позиция изменилась), вы можете объявить это браузеру следующим образом:

will-change: transform, opacity;

Указание того, что именно вы хотите изменить, позволяет браузеру принимать более обоснованные решения относительно тех оптимизаций, которые необходимо выполнить для этих конкретных изменений. Это, очевидно, лучший способ повысить скорость, не прибегая к взлому и не заставляя браузер создавать слои, которые могут быть или не быть необходимыми или полезными.

Источник статьи - все, что нужно знать о CSS-свойствах will-change

Ваш CSS будет

.wallpaper {
    width: 100%;
    height: 100%;
    position: absolute;
    opacity: 0;
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
    will-change: transform, opacity;
    -webkit-animation-timing-function: linear;
}

.animate {
    -webkit-animation-name: fadeInOut;
    -webkit-animation-duration: 6s;
}

@-webkit-keyframes fadeInOut {
    0% {
        opacity: 0;
        -webkit-transform: scale(1);
    }
    16% {
        opacity: 1;
    }
    90% {
        opacity: 1;
    }
    100% {
        opacity: 0;
        -webkit-transform: scale(1.1);
    }
}

Другие полезные источники:

Другие вопросы по тегам