Aujourd’hui nous allons parler de FPS, principalement en CSS, et comment éviter les lags.
Malgré cette image aguicheuse, il ne sera pas question de Counter Strike Source, ni même de First Person Shooter, mais plutôt de Cascade Style Sheet et de Frame per Second.
Dans un jeu de tir demandant des réflexes, les joueurs ont horreur des lags et autres ralentissements.
Il en est de même lorsqu’on créé une animation web: le lag ruine l’expérience de l’utilisateur.
Le web bouge, et s’anime. Depuis quelques années on voit quelques animations en javascript (notamment avec la fonction animate de jQuery, dépassée aujourd’hui mais qui a ouvert la voix) , et désormais en pur CSS.
Maintenant, il faut apprendre à bien utiliser ces propriétés, et s’assurer que nos animations seront le plus fluide possible, c’est ce que nous allons voir maintenant.
Bonnes pratiques pour réaliser ses animations
La première étape est d’ajouter une propriété à ces éléments pour profiter de l’accélération matérielle:
transform: translate3d(0, 0, 0);
ou encore
transform: translateZ(0);
Ca, c’est la base qu’on voit partout (avec les préfixes des navigateurs pour ceux qui ne supportent pas la règle standard).
Mais à quoi ça sert vraiment?
Utiliser le translate3d
Par défaut une page web s’affiche en utilisant les ressources du CPU. En précisant le translate3d, l’élément va être déchargé du CPU et pris en charge par le GPU, et profiter d’une accélération graphique, indispensable pour réaliser ses animations fluides.
Quelle que soit l’animation faite sur son élément, même si on modifie son opacité ou sa taille, il faut ajouter un translate3d pour que le GPU traite l’animation de l’élément. Si on le met que sur certaines animations, on risque de voir un effet de clignotement ou de lag lorsque l’élement passe du CPU au GPU. Il n’y a rien de pire.
Redémarrer ses animations
Par contre, malgré les avancées en terme d’animation de CSS ne gère pas encore correctement le reset des animations. A ce sujet voici un excellent article de CSS tricks avec plusieurs solutions envisagées. La plus clean et plus générique selon moi:
var elm = this, var newone = elm.cloneNode(true); elm.parentNode.replaceChild(newOne, elm);
Le tout en javascript vanilla pour se passer de jQuery et autres librairies.
Bien utiliser Chrome pour analyser ses animations
En ouvrant les paramètres d’une page sous Chrome, via l’icône on peut afficher tout un tas d’informations utiles. La partie qui nous intéresse pour analyser ses animations est dans « Général », la partie « Rendering ».
- Show paint rectangle. Cette partie permet de voir le reflow des éléments de sa page. Il faut éviter que trop d’éléments fasse un reflow en même temps, que toute la page fasse un reflow, et que ses éléments fassent un reflow en continu, même quand ils ne sont pas/plus animés.
- Show FPS meter ajoute un petit cadre en haut à droite de sa page indiquant les FPS de ses animations. Pour ne pas être saccadé il faut rester au dessus de 25 images par seconde, 30 pour être sûr, et 60 signifie que l’animation est très fluide. A droite du cadre Chrome indique également le plus petit FPS et le plus élevé qu’il y ait eu. Sur Chrome mobile on voit en plus la mémoire du GPU utilisée pour les animations, c’est top!
- Enable continuous page repainting force la page à faire constamment un reflow. Généralement une page ne fait pas de reflow total, juste des parties visibles, et pas forcément en continu. L’indicateur montre le temps en ms pris pour le dernier reflow, et le minimum/maximum. L’idéal étant qu’une page atteigne la barre jaune à 30fps, ou mieux, la moitié pour être à 60 fps.
Une fois cette dernière fonctionnalité activée, on peut aller dans l’onglet « Timeline » des paramètres. On peut enregistrer ce qu’il se passe dans le navigateur en cliquant sur « record ».
On peut l’arrêter après quelques images et voir le résultat. Dans la partie « frames » on peut voir le détail de chaque repaint.
En cliquant sur une frame, on peut voir chaque partie de notre page qui est repainte et combien de temps est mis pour chaque bloc.
Ainsi on peut savoir quelle partie du site est longue à dessiner. Bien sûr ce n’est pas forcément ces blocs sont redessinés lors des animations, mais ça permet de voir ce qui ralenti l’affichage des pages. Dans les images prises dans l’exemple on constate qu’un bloc est très long à dessiner. En modifiant un peu la CSS et en l’éditant, ce qui cause le ralentissement du repaint est le bloc principale qui un cumul de box-shadow et border-radius. Chrome ne peut pas fair d’accélération matérielle pour ces éléments, encore plus quand ils sont cumulés. Si on désactive le box-shadow, voilà le changement sur le repaint de la page:
Ca ne veut pas dire qu’il ne faut pas utiliser de box-shadow bien sur, c’est le genre d’évolution dans la mise en page des sites qu’on est content de pouvoir utiliser maintenant! Mais toutes ces nouveautés sont coûteuses en ressources, particulièrement si on veut animer les éléments de sa page. J’espère que cet article vous permettra de bien vérifier la fluidité de vos animations pour avoir un toujours un bon FPS. Des outils similaires existent sur d’autres navigateurs. Safari notamment dispose de très bons outils. A vous de les découvrir!