5

我有一个动画和 JS 用于交替 2 个 div 并更改它们的背景图像(来自几十个图像的数组),有点可互换的 div。一切正常,但是当动画运行时,我可以看到我的 CPU 是 100%。起初我认为这可能是由于 setInterval,但是当我将代码从交替图像更改为每次迭代增加一个数字并将其记录到控制台时 - 我看到 CPU 过载显着减少,大约 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();
});

任何想法如何减少 CPU 过载?

4

1 回答 1

3

答案是CSS 的属性。

will-change是一个属性,它通过让浏览器知道哪些属性和元素即将被操作来优化动画,从而潜在地提高该特定操作的性能。

文章来源:will-change - css 技巧

will-change 属性将使用硬件加速来减少CPU的负载并将 CSS3 动画/转换分配给GPU

旧:translateZ()translate3d()黑客

很长一段时间以来,我们一直在使用所谓的 translateZ()(或 translate3d())hack(有时也称为 null tr​​ansform hack)来欺骗浏览器将我们的动画和变换转换为硬件加速。我们一直在通过向一个不会在 3D 空间中变换的元素添加一个简单的 3D 变换来做到这一点。例如,在二维空间中动画的元素可以通过添加以下简单规则来进行硬件加速:

transform: translate3d(0, 0, 0);

硬件加速操作会导致创建所谓的合成器层,该合成器层上传到 GPU 并由 GPU 合成。但是,强制黑客层创建可能并不总是解决页面上某些性能瓶颈的方法。层创建技术可以提高页面速度,但它们是有代价的:它们占用了系统 RAM 和 GPU 上的内存(特别是在移动设备上受限),并且它们过多会产生不良影响(特别是在移动设备上),所以必须明智地使用它们,并且您需要确保硬件加速您的操作将真正有助于您的页面性能,并且性能瓶颈不是由页面上的另一个操作引起的。

为了避免层创建黑客,引入了一个新的 CSS 属性,它允许我们提前通知浏览器我们可能对元素进行哪些类型的更改,从而允许它优化它如何处理元素,例如在动画实际开始之前执行可能昂贵的工作,为动画等操作做准备。此属性是新的 will-change 属性。

新:Glorious will-change 属性

will-change 属性允许您提前通知浏览器您可能对元素进行哪些类型的更改,以便它可以在需要它们之前设置适当的优化,从而避免非平凡的开始-up 成本,这可能会对页面的响应能力产生负面影响。可以更快地更改和渲染元素,并且页面将能够快速更新,从而带来更流畅的体验。

例如,当在一个元素上使用 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);
    }
}

其他有用的来源:

于 2016-07-08T10:16:07.363 回答