35 votes

Optimisation des feuilles de sprite basées sur SVG pour l'accélération de GPU HW CSS3 dans le navigateur (mobile)

Au cours de la dernière semaine, j'ai aidé un ami à expérimenter avec SVG à base de feuilles sprite dans le navigateur. Nous avons voulu venir avec un flux de travail idéal pour préparer, publier et exécuter de haute qualité des graphiques animés dans le navigateur. Donc, idéalement avoir une seule source de données d'animation qui pourrait fonctionner pour les petits écrans de smartphone, les tablettes, les écrans de la rétine, et les navigateurs de bureau.

En théorie, (vectoriel) SVG doit être idéal pour cela, mais depuis SVG n'est généralement pas utilisé beaucoup - nous avons décidé de le tester. L'idée était de ne pas utiliser SVG, SMIL (donc pas de SVG d'animation), mais au lieu de créer une animation de sprite-feuille (comme vous le feriez normalement avec des données raster PNG/JPG) mais le faire avec de la pure vecteurs c'est à dire le format SVG. Sa a été un peu plus grand, mais si ça fonctionne, ce serait encore avec quelque chose des thats encore plus optimisé.

Plus image-par-image de vecteur d'animation pourrait faire de grandes choses pour notre méthode de travail - il nous permettant d'utiliser le Flash de l'éditeur pour faire des animations et de les exporter au format SVG feuilles sprite.

De toute façon, le résultat fonctionne étonnamment bien , mais échoue également dans certains secteurs (veuillez noter que, pour des fins de test, nous avons seulement travaillé avec Webkit, c'est à dire les navigateurs Safari, Chrome, Safari mobile sur iOS et Android ICS).

En CSS, il est assez facile de déclencher une accélération matérielle pour une feuille sprite comme ça (au moins dans les navigateurs modernes avec des images clés et des étapes) - il vous suffit de faire ceci:

background-image: url(my.svg);
-webkit-animation: walk 1s steps(12, end) infinite; 

d'appel d'animation par image clé montré ici:

@-webkit-keyframes walk {
    from { -webkit-transform: translate3d(0, 0, 0); }
    to { -webkit-transform: translate3d(-100%, 0, 0); }          
}

d'où l'utilisation de translate3d devrait laisser GPU coup de pied dans et le tout doit être accéléré par le matériel dans iOS mobile Safari et Android ICS navigateur.

Ce qui est assez étonnant compte tenu que c'est une sorte de brute-force technique et un assez grand vecteur d'animation (600x600px pour le test) - le tout de mouches. Mais ce n'est pas parfait - il scintille dans Safari avant de décoller. Et dans l'ICS navigateur son scintillement tout le temps donc ce n'est pas vraiment utilisable.

Nous avons donc essayé l'habitude des trucs pour se débarrasser de scintillement, tels que:

-webkit-transform: translateZ(0);    
-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;

Mais cela ne fonctionne pas. Nous avons donc essayé de pixellisation SVG dynamiquement en mémoire et en l'utilisant comme une texture avec -webkit-transform: scale3d(1, 1, 0) mais cela n'a pas aidé à l'éther.

Enfin, nous avons juste remplacé le SVG avec un rendu PNG/JPG feuille sprite de la même taille de la pensée, le complexe vecteurs sont tout simplement trop beaucoup pour le navigateur, mais devinez quoi? C'est la même question, de sorte que son pas de rendu SVG à tous - ses un navigateur dessin en question. Une preuve de plus de qui est, si nous ralentir l'animation en bas à 1IPS - clignotement persiste encore.

L'image est trop grosse pour le GPU? Avons-nous atteint la limite de performance de ce que vous êtes en mesure de facilement dessiner/animer dans le navigateur (mobile en particulier)?

Je voudrais vraiment l'apprécier idées/hacks sur la façon de potentiellement se débarrasser de la lueur (surtout depuis son vraiment très rapide). C'est juste une technique prometteuse - haute performance navigateur animation qui s'adapte aux différentes tailles d'écran - l'HTML5 Saint Graal ;)

Avec quelques optimisations telles que

<svg preserveAspectRatio="xMinYMax slice" viewBox="0 0 600 50">

et un peu de CSS de la magie, nous sommes en mesure de SVG s'adapter à son conteneur parfaitement et modifier sa taille à partir d'une seule classe CSS. Il serait vraiment faire des merveilles - mais, hélas, le scintillement.

De toute façon - s'il vous plaît lire plus à ce sujet ici où vous êtes également en mesure de l'essayer.

3voto

Tom Carchrae Points 3322

Idée assez cool.

Pourquoi ne pas changer le zindex des cadres afin de superposer les images les unes sur les autres? Cela pourrait résoudre le scintillement car, lors du redessinage, la dernière image est toujours visible. Donc, il vous suffira de continuer à augmenter la valeur zindex de la dernière image. Bien sûr, il y a une limite à cela et vous devrez réinitialiser à nouveau le zindex, mais cela pourrait avoir un impact important sur la réduction du scintillement.

1voto

CupawnTae Points 2307

Je n'ai pas de ICS ici pour le vérifier, mais sur iOS 6 sur un iPhone 5 et Jelly Bean 4.1.1 sur un Galaxy Nexus, l'animation a l'air assez lisse, sauf quand je zoom, à quel point je reçois quelques flickery images et puis il s'installe à nouveau.

Ce qui m'a rappelé un problème similaire, j'ai eu le rendu sur une toile de grand format et de la transformer autour de l'écran (avec la majorité de la toile à l'écran à un moment donné).

Ma boîte noire de l'analyse à l'époque suggéré il y a quelques optimisation où le navigateur n'était pas la peine de rendre à l'écran du contenu, plutôt que d'attendre qu'il est devenu visible, qui a complètement défait le but d'avoir l'image de grande taille et de matériel d'accélération autour de.

Ma "solution" est de -webkit-transform: l'échelle de l'ensemble de l'image vers le bas assez petit pour garantir tout cela correspond à l'écran (si le navigateur n'a pas le choix mais pour rendre l'ensemble de l'image), laissez-le rendu, et ensuite l'échelle à la taille que je voulais.

(En aparté: pour masquer ce hackery de l'utilisateur, j'ai d'abord expérimenté avec réglage de l'opacité: 0 de sorte que le pré-rendu ne serait pas visible, mais il semble que cela a le même effet que les limites de l'écran de rendu, il a obtenu optimisé à. Au final, j'ai mis l'opacité très faible et le couvrit d'un presque opaque message "chargement", ce qui signifie le rendu en arrière-plan n'était pas visible à l'œil nu, mais le navigateur a pas, dans l'absolu visibles/invisibles pour optimiser l'extérieur. Vous ne savez pas si cela a été exagéré, mais il a semblé fonctionner pour mon installation.)

Je serais très intéressé de savoir si une technique similaire peut travailler pour vous.

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