88 votes

L'utilisation du processeur de l'animation par images clés CSS est élevée. Est-ce normal ?

J'utilise l'animation par image clé suivante sur plusieurs éléments :

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

Sur mon ordinateur, l'utilisation du processeur est d'environ 40 % dans Chrome et Firefox. Est-ce l'état actuel des animations (agréables mais inutilisables pour l'instant) ou est-ce qu'il me manque une propriété magique ?

Vous pouvez vérifier l'échantillon suivant avec la même animation : http://jsfiddle.net/Nrp6Q/

101voto

skyline3000 Points 5299

Oui, c'est normal car vous avez plusieurs animations en boucle infinie sur la page. Le processeur effectue donc un travail continu pendant que ces éléments sont rendus. Il existe une propriété "magique" qui permet de réduire considérablement l'utilisation du CPU :

transform: translateZ(0);

Cela composera les éléments dans leurs propres couches (en faisant croire au navigateur qu'il effectuera des transformations 3D) et le navigateur devrait, dans la plupart des cas, profiter de l'accélération du GPU, réduisant ainsi la charge sur le CPU. Pour moi, cela a réduit la charge d'environ 20% (presque la moitié).

Pour en savoir plus sur cette technique, consultez le site : http://ariya.blogspot.com/2011/07/fluid-animation-with-accelerated.html

En outre, plus il y a d'images clés dans l'animation, plus c'est difficile. Essayez l'animation en supprimant l'image-clé du milieu et vous constaterez une autre baisse substantielle (~10-12%) de l'utilisation du CPU.

Enfin, toutes les propriétés ne sont pas égales : il est beaucoup plus difficile pour le navigateur d'animer de manière fluide le box-shadow que, par exemple, la couleur d'arrière-plan. En laissant toutes les images clés intactes, mais en supprimant la propriété box-shadow et en utilisant l'astuce translateZ(0), l'utilisation du processeur n'a atteint que 10 à 11 %.

Même si cela me fait mal de le dire, pour les animations en boucle infinie, un fichier .gif animé sera beaucoup plus performant que CSS3 dans l'état actuel de l'animation des navigateurs, surtout si vous prévoyez que beaucoup d'entre elles restent affichées sur la page pendant un certain temps.

Mise à jour 2017 :

Pour ceux qui n'ont pas encore trouvé leur chemin vers cette question et cette réponse, translate3d(0, 0, 0) offre le même avantage que translateZ(0) tu es juste aussi en train de mettre translateX() y translateY() en même temps. Veuillez ignorer le commentaire de @Farside comme il utilise translate3d(X, Y, Z) dans sa démo mais ne le compare pas à translate(X, Y) ce qui montrerait que l'utilisation de cette technique fait toujours une différence significative.

Selon cette question certaines personnes ont constaté une meilleure performance sur tous les navigateurs, en particulier Chrome, avec transform: rotateZ(360deg) .

21voto

Farside Points 5304

L'un des moyens possibles de réduire la charge sur le CPU est d'utiliser une méthode appelée null transform hack qui est souvent salué comme une sorte de balle d'argent . Dans de nombreux cas, il améliorera considérablement les performances de rendu dans les navigateurs WebKit et Blink comme Chrome, Opera et Safari.

Utilisation du "Null transform hack" (un mode de compositing matériel)

Le hack de la transformation nulle fait essentiellement deux choses :

  1. Il allume le mode de composition matérielle (en supposant qu'il soit supporté par la plateforme)
  2. Il crée une nouvelle couche avec sa propre surface d'appui

Pour "forcer" un navigateur, il suffit d'ajouter l'une de ces propriétés CSS à l'élément :

transform: translateZ(0);

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

Lorsque vous travaillez avec des transformations 3D, il est bon d'avoir également ces propriétés pour améliorer les performances :

backface-visibility: hidden;
perspective: 1000;

Mises en garde concernant le "hack de la transformation nulle".

L'activation d'une accélération matérielle en CSS3 pour un grand nombre d'objets peut ralentir les performances ! Apparemment, chaque transformation 3D nulle crée une nouvelle couche. Cependant, forcer la création de couches n'est pas toujours la solution à certains goulots d'étranglement en matière de performances sur une page. Les techniques de création de couches peuvent améliorer la vitesse de la page, mais elles ont un coût : elles occupent de la mémoire dans la RAM du système et sur le GPU. Ainsi, même si le GPU fait un bon travail, le transfert de nombreux objets peut poser problème, de sorte que l'utilisation de l'accélération GPU n'en vaut peut-être pas la peine. La citation de W3C :

Cependant, la mise en place de l'élément dans un nouveau calque est une opération relativement coûteuse, qui peut retarder le démarrage d'une animation de transformation d'une fraction de seconde appréciable.

Le déplacement de quelques gros objets est plus performant que le déplacement d'un grand nombre de petits objets avec l'accélération 3D. Donc ils doivent être utilisés à bon escient et vous devez vous assurer que l'accélération matérielle de votre opération améliorera réellement les performances de votre page et que le goulot d'étranglement n'est pas causé par une autre opération sur votre page.

De plus, un GPU est conçu spécifiquement pour effectuer les calculs mathématiques/géométriques complexes, et décharger les opérations sur l'ordinateur de l'utilisateur. Le GPU peut entraîner une consommation massive d'énergie . Évidemment, lorsque le matériel entre en jeu, la batterie de l'appareil cible l'est aussi.

La voie moderne : le will-change propriété

Le progrès ne se trouve pas à un seul endroit... Le W3C a introduit le will-change Propriété CSS. Pour faire court, la propriété will-change vous permet d'informer le navigateur à l'avance des types de modifications que vous êtes susceptible d'apporter à un élément, afin qu'il puisse mettre en place les optimisations appropriées avant qu'elles ne soient nécessaires.

Voici ce qu'ils disent dans le projet :

En will-change définie dans cette spécification permet à un auteur de déclarer à l'avance quelles propriétés sont susceptibles de changer à l'avenir, afin que l'UA puisse mettre en place les optimisations appropriées quelque temps avant qu'elles ne soient nécessaires. De cette façon, lorsque le changement réel se produit, la page est mise à jour rapidement.

Utilisation de will-change Pour indiquer au navigateur une transformation à venir, il suffit d'ajouter cette règle à l'élément qui doit être transformé :

will-change: transform;

Lorsqu'ils développent des applications mobiles, les développeurs sont obligés de prendre en compte les nombreuses contraintes des appareils tout en écrivant des applications web mobiles. Les navigateurs deviennent de plus en plus intelligents et, parfois, il vaut mieux laisser la décision à la plate-forme elle-même, plutôt que de superposer les accélérations et de forcer le comportement de façon fantaisiste.

5voto

konrad_pe Points 745

J'ai eu un cas similaire d'utilisation élevée du CPU lors de l'animation de certains éléments avec CSS3. J'animais la propriété "left" de ~7 éléments, avec quelques propriétés d'opacité et d'ombre utilisées dans toute ma page. J'ai décidé de passer à jQuery.animate, ce qui n'a malheureusement pas amélioré les performances du tout. Mon processeur (i7) était toujours à ~9-15% lors de l'affichage de la page, plusieurs astuces (translateZ, etc) n'ont pas vraiment amélioré les performances non plus - tout en ayant ma mise en page désordonnée (certains éléments positionnés de façon absolue étaient impliqués, ouch !).

Puis je suis tombée sur cette merveilleuse extension : http://playground.benbarnett.net/jquery-animate-enhanced/

J'ai simplement référencé le fichier .js, sans apporter la moindre modification aux transitions jQuery, et l'utilisation de mon processeur est maintenant de 1 à 2 % sur la même page.

Ma recommandation : lorsque vous rencontrez des problèmes de processeur en utilisant des transitions CSS3, passez à jQuery + le plugin animate-enhanced.

3voto

user1467439 Points 379

Vous pouvez également l'utiliser sur n'importe lequel des éléments de classe suivants où vous souhaitez utiliser le GPU au lieu du CPU

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

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

1voto

Oleg K Points 41

Pour un cas particulier d'animation de fond "pulsée", signalé ici, j'ai trouvé une solution css+js.

Dans mon cas, l'animation de l'arrière-plan se faisait sur la propriété background-position plutôt que sur la background-color, mais le principe est le même.

Disons que vous avez un bloc avec un arrière-plan particulier :

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

Stylisons-le : (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;
  }
}

Il est maintenant temps de faire en sorte que l'effet se produise en ajoutant une classe "animated" au bloc avec du 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 ();

Dans mon cas, les performances ont été améliorées d'environ 15 fois.

(i) Note pour calculer correctement les secondes pour la transition et les délais d'attente à la fois dans css et js si vous voulez des valeurs différentes de 5 secondes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X