les performance de rendu sur mobile

Post on 19-Jul-2015

365 Views

Category:

Engineering

3 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Les performances de rendu

Jean-Pierre VincentArchitecte itinérant

Consultant et Formateur Perfs ou JS

@theystolemynick

POURQUOI FAIRE ?

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

Pour faire plaisir à Dieu

Pour faire des interfaces très réactive

Pour des interactions plus riches

Avoir 60 Fps ou pas

Comment fluidifier ?

$(‘.el1’).animate(

{ left: ‘-=600’

},

{ duration: 350,

easing:

‘bounce’

}

);

$(‘.el2’).animate …

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

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 !

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’)

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;

}

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

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

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

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

Bonus : forcer le GPU (parfois)

.move-left {

transform:translate3d(-600px, 0, 0);

}

.enlarge-your p {

transform:scale3d(1.3, 0, 0);

}

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);

}

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

60 FPS FTW

LES ANIMATIONS IMPRÉVISIBLES

Et pour les animations imprévisibles ?

• Parallax

• Drag

• Jeux vidéos

• …

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

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érervar width = el.offsetWidth;

$(el).on(‘touchmove’, function move() {

// un set, et même plusieurs d’affilé : SMOOTH

this.style.width = ( width += Y );

}

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

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();

}());

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);

});

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

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 );

})();

Calculs lourds ?

La technique ancestrale du

setTimeout( fn, 0);

Universel, increvable, lisible avec le bon snippet

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

DOM : la taille compte

(et la manière dont on s’en sert)

DOM Monster yellowlab.tools

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

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(){} )

MAÎTRISER SES OUTILS

Assez de règles

Profilers — Android & Desktop

Profilers — Firefox & Firefox OS

Profilers natifs — iOS & desktop

Les autres

• Opera : dragonfly

• IE8 : profiling JS

À l’instinct™ :

• iOS < 7

• Navigateur Android

• …

Librairies d’animation CSS 3

• Librairies CSS:– animate.css,

– Effekt.css

• Librairies JS : – D3.js,

– GSAP,

– TweenJS,

– jQuery 4

Conclusion

• JS seul est performant, merci de demander

• Watch your DOM !

• Use the CSS 3 / HTML5 force Luke

Je testerais, tu testeras,nous testerons …

MERCI

Jean-Pierre Vincent

@theystolemynick

Un audit ou une petite formation Perfs ? jp@braincracking.fr

top related