Les Performance de rendu sur mobile

1 757 vues

Publié le

Comment avoir un rendu performant même sur mobile ? Comment animer convenablement ses interfaces Web ? Quelques pistes et retours d'expérience.
Présenté en 2015 pour le JS Open days 1

Publié dans : Ingénierie
  • Soyez le premier à commenter

Les Performance de rendu sur mobile

  1. 1. Les performances de rendu Jean-Pierre Vincent Architecte itinérant Consultant et Formateur Perfs ou JS @theystolemynick
  2. 2. POURQUOI FAIRE ?
  3. 3. Pour faire plaisir à l’utilisateur (et ton CA) Temps de réponse : • < 150 ms : instantané – Le but de toute interface touch • 150 ms — 1 s : c’est la machine qui bosse – L’utilisateur stresse • > 10s : bye bye Animations : • 60 Fps : fluide et naturel • < 30 Fps : bye bye
  4. 4. Pour faire plaisir à Dieu
  5. 5. Pour faire des interfaces très réactive
  6. 6. Pour des interactions plus riches
  7. 7. Avoir 60 Fps ou pas
  8. 8. Comment fluidifier ? $(‘.el1’).animate( { left: ‘-=600’ }, { duration: 350, easing: ‘bounce’ } ); $(‘.el2’).animate …
  9. 9. Les ordres de grandeur 60 Hz = 16 ms pour : • JS – Récupérer la position de l’élément – Calcul de la nouvelle position – Appliquer la nouvelle position • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
  10. 10. Les manipulations DOM en JS • el.offsetLeft …, el.clientLeft…, el. getBoundingClientRect()… • el.scrollTo(), el.scrollTop, w.innerHeight • el.getComputedStyle() • evt.layerX, evt.offsetX • SVG.getCharNumAtPosition(), SVG.getNumberOfChars() jQuery.animate() utilise tout cela !
  11. 11. Animation prédictible ? JS quasi inutile • On trash jQuery.animate • Pré-calcul des styles • JS se limite à ajouter / supprimer des classes El1.addClass(‘disappear-to-left’) El2.addClass(‘appear-from-right’)
  12. 12. Animation prédictible : transition CSS .elements { transition-property : left; transition-timing-function: cubic- bezier(0,0,0.25,1); transition-duration : 350 ms; left: 600px; } .appear-from-right { left: 0; } .disappear-to-left { left: -600px; }
  13. 13. Transitions CSS • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position – Appliquer la nouvelle position • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
  14. 14. Les propriétés qui coûtent cher Elles déclenchent Layout + Paint + Composite • top, left, width, height, float • font-*, border-*, padding-*, margin-* • display, visibility csstriggers.com
  15. 15. Les propriétés qui vont bien .move-left{ transform: translateX(-600px); } .enlarge-your p { transform : scale(1.3, 0) ; } • IE 8 : ms-filters, IE9 : prefix ms- • IE10, chrome, Fx, OS mobile : standard
  16. 16. CSS transform / opacity • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position – Appliquer la nouvelle position • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
  17. 17. Bonus : forcer le GPU (parfois) .move-left { transform:translate3d(-600px, 0, 0); } .enlarge-your p { transform:scale3d(1.3, 0, 0); }
  18. 18. Transition + translation + GPU = <3 .elements { transition-property : transform; transition-timing-function: cubic- bezier(0,0,0.25,1); transition-duration : 350 ms; left: 600px; } .appear-from-right { transform: translate3d(-600px, 0px, 0px); } .disappear-to-left { transform: translate3d(-1200px, 0px, 0px); }
  19. 19. Transition + translation + GPU = <3 • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position – Appliquer la nouvelle position • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
  20. 20. 60 FPS FTW
  21. 21. LES ANIMATIONS IMPRÉVISIBLES
  22. 22. Et pour les animations imprévisibles ? • Parallax • Drag • Jeux vidéos • …
  23. 23. Reprenons • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position – Appliquer la nouvelle position • Navigateur – Calculs de Layout <= optimisé en CSS – Paint des zones modifées <= optimisé en CSS – Pousser vers la carte graphique
  24. 24. Récupérer la position : mise en cache • Plutôt que $(el).on(‘touchmove’, function move() { // get + set du DOM en boucle : BOOM this.style.width = (this.offsetWidth + X); } • Préférer var width = el.offsetWidth; $(el).on(‘touchmove’, function move() { // un set, et même plusieurs d’affilé : SMOOTH this.style.width = ( width += Y ); }
  25. 25. Reprenons • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position – Appliquer la nouvelle position • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
  26. 26. Quand mettre à jour le DOM ? // JAMAIS setInterval( move, 16 ); // MIEUX, mais agressif et imprécis (function boucle() { setTimeout( boucle, 16); move(); }()); // AU TOP (function boucle() { requestAnimationFrame( boucle); move(); }());
  27. 27. Alléger var height = el.offsetHeight, Y = 0; $(el).on(‘touchmove’, function calculateDelta() { … // Calcul séparé de Y (delta du doigt) }); requestAnimationFrame( function move() { … // check de la nécessité puis Raf(move) this.style.height = (height += Y); });
  28. 28. Reprenons • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position <= dissocié – Appliquer la nouvelle position <= optimisé • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
  29. 29. Calculs lourds ? var IA = new Worker(‘game-ia.js’); var positions; IA.addEventListener(‘moves’,function(e){ positions = e.data; }); (function boucle() { requestAnimationFrame( boucle ); moveUnits( positions ); })();
  30. 30. Calculs lourds ? La technique ancestrale du setTimeout( fn, 0); Universel, increvable, lisible avec le bon snippet
  31. 31. Reprenons • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position <= dissocié et optimisé – Appliquer la nouvelle position <= optimisé • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
  32. 32. DOM : la taille compte (et la manière dont on s’en sert) DOM Monster yellowlab.tools
  33. 33. Touche pas (trop) à mon DOM • Peu de requête DOM – Mise en cache des résultats en dehors des boucles • Appliquer en batchs – $el.addClass(‘error’) plutôt que $el.css – .innerHTML marche encore ! – Pas d’alternance get / set
  34. 34. Apprends à faire tes sélecteurs • Natif quand tu peux : $(document.getElementById(‘id’)) VS $(‘#id’) document.querySelector(‘.item’) VS $(‘.item’).first() • Limiter l’étendue de la recherche $container.find(‘.item’) $container.find(‘ > li.item’) • Déléguer $container.on( ‘click’, ‘li’, function(){} )
  35. 35. MAÎTRISER SES OUTILS Assez de règles
  36. 36. Profilers — Android & Desktop
  37. 37. Profilers — Firefox & Firefox OS
  38. 38. Profilers — Windows
  39. 39. Profilers natifs — iOS & desktop
  40. 40. Les autres • Opera : dragonfly • IE8 : profiling JS À l’instinct™ : • iOS < 7 • Navigateur Android • …
  41. 41. Librairies d’animation CSS 3 • Librairies CSS: – animate.css, – Effekt.css • Librairies JS : – D3.js, – GSAP, – TweenJS, – jQuery 4
  42. 42. Conclusion • JS seul est performant, merci de demander • Watch your DOM ! • Use the CSS 3 / HTML5 force Luke Je testerais, tu testeras, nous testerons …
  43. 43. MERCI Jean-Pierre Vincent @theystolemynick Un audit ou une petite formation Perfs ? jp@braincracking.fr

×