Graphiques / graphiques interactifs rapides et réactifs: SVG, Canvas, autre?

114

J'essaie de choisir la bonne technologie à utiliser pour mettre à jour un projet qui rend essentiellement des milliers de points dans un graphique zoomable et panoramique. L'implémentation actuelle, utilisant Protovis, est sous-performante. Vérifiez le ici:

http://www.planethunters.org/classify

Il y a environ 2000 points lors d'un zoom arrière complet. Essayez d'utiliser les poignées en bas pour zoomer un peu et faites-les glisser pour vous déplacer. Vous verrez qu'il est assez instable et que votre utilisation du processeur va probablement jusqu'à 100% sur un cœur à moins que vous n'ayez un ordinateur très rapide. Chaque modification de la zone de mise au point appelle un redessiner à protovis qui est sacrément lent et est pire avec plus de points dessinés.

Je voudrais apporter quelques mises à jour à l'interface ainsi que changer la technologie de visualisation sous-jacente pour être plus réactive avec l'animation et l'interaction. D'après l'article suivant, il semble que le choix soit entre une autre bibliothèque SVG ou une bibliothèque basée sur un canevas:

http://www.sitepoint.com/how-to-choose-between-canvas-and-svg/

d3.js , issu de Protovis, est basé sur SVG et est censé être meilleur pour le rendu des animations . Cependant, je ne suis pas certain de savoir à quel point il est meilleur et quel est son plafond de performance. Pour cette raison, j'envisage également une refonte plus complète en utilisant une bibliothèque basée sur le canevas comme KineticJS . Cependant, avant d'aller trop loin dans l'utilisation d'une approche ou d'une autre, j'aimerais entendre quelqu'un qui a fait une application Web similaire avec autant de données et avoir son opinion.

Le plus important est la performance, avec un accent secondaire sur la facilité d'ajouter d'autres fonctionnalités d'interaction et de programmer l'animation. Il n'y aura probablement pas plus de 2000 points à la fois, avec ces petites barres d'erreur sur chacun. Le zoom avant, arrière et le panoramique doivent être fluides. Si les bibliothèques SVG les plus récentes sont correctes à cet égard, alors peut-être que la facilité d'utilisation de d3 l'emportera sur la configuration accrue de KineticJS, etc. préférerait certainement aller dans cette direction.

Exemple d'application créée par le NYTimes qui utilise SVG, mais qui s'anime toujours de manière acceptable: http://www.nytimes.com/interactive/2012/05/17/business/dealbook/how-the-facebook-offering-compares.html . Si je peux obtenir cette performance et ne pas avoir à écrire mon propre code de dessin sur toile, j'opterais probablement pour SVG.

J'ai remarqué que certains utilisateurs ont utilisé un hybride de manipulation de d3.js combiné avec un rendu sur toile . Cependant, je ne peux pas trouver beaucoup de documentation à ce sujet en ligne ou entrer en contact avec le PO de ce poste. Si quelqu'un a une expérience dans ce genre d' implémentation DOM-to-Canvas ( démo , code ), j'aimerais également avoir de vos nouvelles. Cela semble être un bon hybride de pouvoir manipuler les données et d'avoir un contrôle personnalisé sur la façon de les rendre (et donc les performances), mais je me demande si devoir tout charger dans le DOM va encore ralentir les choses.

Je sais qu'il existe des questions similaires à celle-ci, mais aucune d'entre elles ne pose exactement la même chose. Merci de votre aide.

Suivi : l'implémentation que j'ai fini par utiliser est sur https://github.com/zooniverse/LightCurves

Andrew Mao
la source
"La chose la plus importante est la performance, avec un accent secondaire sur la facilité d'ajouter d'autres interactions" +1 pour canvas
philipp
La question est la suivante: SVG est-il suffisant sur la plupart des navigateurs pour 2k points + autres éléments de graphique? Si tel est le cas, et que la lenteur est simplement due à des faiblesses de protovis, je préfère m'en tenir au SVG.
Andrew Mao
1
Mike Bostock a déjà donné une bonne réponse. Pour quelques informations supplémentaires, vous pouvez consulter ces deux ressources: stackoverflow.com/questions/5882716/html5-canvas-vs-svg-vs-div/… blogs.msdn.com/b/ie/archive/2011/04/22 /…
Ümit le
8
Suivi: J'ai implémenté cela avec une approche hybride SVG / canevas, où le SVG prend en charge les axes et les lignes de quadrillage et le canevas peut rendre les points extrêmement rapidement. C'est super rapide!
Andrew Mao

Réponses:

183

Heureusement, dessiner 2000 cercles est un exemple assez facile à tester. Voici donc quatre implémentations possibles, deux chacune de Canvas et SVG:

Ces exemples utilisent le comportement de zoom de D3 pour implémenter le zoom et le panoramique. Indépendamment de savoir si les cercles sont rendus dans Canvas ou SVG, l'autre distinction majeure est de savoir si vous utilisez un zoom géométrique ou sémantique .

Le zoom géométrique signifie que vous appliquez une seule transformation à l'ensemble de la fenêtre: lorsque vous effectuez un zoom avant, les cercles deviennent plus grands. Le zoom sémantique en contraste signifie que vous appliquez des transformations à chaque cercle individuellement: lorsque vous effectuez un zoom avant, les cercles restent de la même taille mais ils s'étalent. Planethunters.org utilise actuellement le zoom sémantique, mais il peut être utile de considérer d'autres cas.

Le zoom géométrique simplifie la mise en œuvre: vous appliquez une fois une translation et une mise à l'échelle, puis tous les cercles sont re-rendus. L'implémentation SVG est particulièrement simple, mettant à jour un seul attribut "transform". Les performances des deux exemples de zoom géométrique semblent plus que suffisantes. Pour le zoom sémantique, vous remarquerez que D3 est nettement plus rapide que Protovis. C'est parce qu'il fait beaucoup moins de travail pour chaque événement de zoom. (La version Protovis doit recalculer tous les attributs sur tous les éléments.) Le zoom sémantique basé sur Canvas est un peu plus rapide que SVG, mais le zoom sémantique SVG semble toujours réactif.

Pourtant, il n'y a pas de solution miracle pour la performance, et ces quatre approches possibles ne commencent pas à couvrir tout l'espace des possibles. Par exemple, vous pouvez combiner le zoom géométrique et sémantique, en utilisant l'approche géométrique pour le panoramique (mise à jour de l'attribut «transform») et en ne redessinant que des cercles individuels pendant le zoom. Vous pourriez probablement même combiner une ou plusieurs de ces techniques avec des transformations CSS3 pour ajouter une accélération matérielle (comme dans l' exemple de regroupement hiérarchique des bords ), bien que cela puisse être difficile à implémenter et puisse introduire des artefacts visuels.

Néanmoins, ma préférence personnelle est de conserver autant de fichiers SVG que possible et d'utiliser Canvas uniquement pour la "boucle interne" lorsque le rendu est le goulot d'étranglement . SVG a tellement de commodités pour le développement - telles que CSS, les jointures de données et l'inspecteur d'éléments - qu'il est souvent une optimisation prématurée de commencer avec Canvas. La combinaison de Canvas avec SVG, comme dans la visualisation Facebook IPO que vous avez liée, est un moyen flexible de conserver la plupart de ces commodités tout en obtenant les meilleures performances. J'ai également utilisé cette technique dans Cubism.js , où le cas particulier de la visualisation de séries temporelles se prête bien à la mise en cache bitmap.

Comme le montrent ces exemples, vous pouvez utiliser D3 avec Canvas, même si certaines parties de D3 sont spécifiques à SVG. Voir également ce graphique dirigé par la force et cet exemple de détection de collision .

mbostock
la source
Wow, c'était une réponse géniale, et du maître de la visualisation lui-même! Je pense que je devrais m'en tenir au zoom sémantique, et sur mon ordinateur, le moteur de rendu basé sur le canevas est beaucoup plus rapide que la version SVG lors du panoramique / zoom (peut-être avoir à voir avec l'implémentation du navigateur?). Ce que vous avez dit à propos de l'utilisation de SVG avec canvas comme boucle interne est exactement ce que je cherchais à confirmer, et les exemples de code ne sont qu'un joli bonus. Merci beaucoup!
Andrew Mao
J'ai juste eu l'idée d'essayer les exemples de zoom arrière sémantique sur différents navigateurs: Chrome, tous deux assez rapides, je ne peux pas faire la différence; IE: SVG légèrement plus lent; Firefox (dernier commentaire): SVG est très lent comparé à canvas. Je suppose que cela complique également un peu la décision, mais fait du rendu sur toile un choix sûr. Une dernière question: l'utilisation de KineticJS au lieu de canvas va-t-elle affecter directement les performances de manière significative?
Andrew Mao
1
Andrew, un peu en retard mais voici mon expérience avec FF: ça rattrape. J'avais l'habitude d'exécuter les transitions FF 15 et D3 SVG rapidement commencé à devenir lent. Mais chaque nouvelle version est devenue nettement plus rapide. Maintenant, je suis sur FF 18 beta et c'est rapide par rapport à 17. Je ne sais pas si c'est aussi lisse que le chrome.
user2503795
@AndrewMao Bonjour Andrew, je me retrouve dans une situation où il semble que le rendu soit le goulot d'étranglement. J'ai besoin de faire un panoramique et de zoomer sur certains points et environ 6000 trajectoires de courbe. stackoverflow.com/questions/17907769/svg-path-rendering-speed/... Mais je ne comprends pas très bien Bostock quand il a dit "garder autant de SVG que possible, et n'utiliser Canvas que pour la" boucle intérieure "" que j'ai regardé les quatre exemples cependant .. Pourriez-vous m'éclairer?
kakacii
@kakacii est-ce que la transformation est également lente dans tous les navigateurs? Si tel est le cas, je dirais que vous utilisez le mauvais code ou que vous avez atteint les limites du rendu du navigateur. Si vous pouviez publier du code, je pourrais peut-être vous aider. mbostock faisait référence à l'utilisation de SVG pour la simplicité de la manipulation et du canevas uniquement si nécessaire car il est plus compliqué à coder. Cependant, des bibliothèques telles que KineticJS ont dans une certaine mesure simplifié cela.
Andrew Mao
8

Je pense que dans votre cas, la décision entre la toile et le svg n'est pas comme une décision entre «monter à cheval» ou conduire une «Porsche». Pour moi, cela ressemble plus à la décision concernant la couleur des voitures.

Laissez-moi vous expliquer: en supposant que, sur la base du cadre, les opérations

  • dessine une étoile,
  • ajouter une étoile et
  • supprimer une étoile

prendre un temps linéaire. Donc, si votre décision concernant le framework était bonne, c'est un peu plus rapide, sinon un peu plus lent.

Si vous continuez à supposer que le framework est juste rapide, alors il devient totalement évident que le manque de performance est causé par le grand nombre d'étoiles et que leur gestion est quelque chose qu'aucun des frameworks ne peut faire pour vous, du moins je ne sais pas à propos de ça.

Ce que je veux dire, c'est que la base du problème conduit à un problème de base de la géométrie de calcul, à savoir: la recherche de distance et un autre d'infographie: le niveau de détail .

Pour résoudre votre problème de performances, vous devez implémenter un bon préprocesseur capable de trouver très rapidement les étoiles à afficher et peut-être capable de regrouper les étoiles qui sont proches les unes des autres, en fonction du zoom. La seule chose qui garde votre vue vive et rapide est de garder le nombre d'étoiles à dessiner aussi bas que possible.

Comme vous l'avez dit, le plus important est la performance, alors que j'aurais tendance à utiliser canvas, car cela fonctionne sans opérations DOM. Il offre également la possibilité d'utiliser webGL, ce qui augmente considérablement les performances graphiques.

BTW: avez-vous vérifié paper.js ? Il utilise le canevas, mais émule les graphiques vectoriels.

PS: Dans ce livre, vous pouvez trouver une discussion très détaillée sur les graphiques sur le Web, les technologies, les avantages et les inconvénients de canvas, SVG et DHTML.

philipp
la source
7

J'ai récemment travaillé sur un tableau de bord en temps quasi réel (actualisé toutes les 5 secondes) et j'ai choisi d'utiliser des graphiques qui se rendent à l'aide de canevas.

Nous avons essayé Highcharts (bibliothèque de graphiques JavaScript basée sur SVG) et CanvasJS (bibliothèque de graphiques JavaScript basée sur Canvas). Bien que Highcharts soit une API de création de graphiques fantastique et offre bien plus de fonctionnalités, nous avons décidé d'utiliser CanvasJS.

Nous devions afficher au moins 15 minutes de données par graphique (avec l'option de choisir une plage de deux heures maximum).

Donc, pendant 15 minutes: 900 points (points de données par seconde) x2 (graphique de combinaison de lignes et de barres) x4 graphiques = 7200 points au total.

En utilisant le profileur de chrome, avec CanvasJS, la mémoire n'a jamais dépassé 30 Mo alors qu'avec Highcharts, l'utilisation de la mémoire dépassait 600 Mo.

De plus, avec un temps de rafraîchissement de 5 secondes, le rendu CanvasJS était plus réactif que Highcharts.

Nous avons utilisé une minuterie (setInterval 5 secondes) pour effectuer 4 appels d'API REST afin d'extraire les données du serveur principal qui s'est connecté à Elasticsearch. Chaque graphique mis à jour au fur et à mesure que les données sont reçus par JQuery.post ().

Cela dit, pour les rapports hors ligne, j'irais avec Highcharts depuis son API plus flexible.

Il y a aussi des graphiques Zing qui prétendent utiliser SVG ou Canvas mais ne les ont pas regardés.

Le canevas doit être pris en compte lorsque les performances sont vraiment essentielles. SVG pour la flexibilité. Non pas que les frameworks de canevas ne soient pas flexibles, mais il faut beaucoup plus de travail pour que le framework de canevas obtienne les mêmes fonctionnalités qu'un framework svg.

utilisateur432024
la source
3

Pourrait également regarder dans Meteor Charts, qui est construit sur le framework KineticJS ultra rapide: http://meteorcharts.com/

Eric Rowell
la source
0

J'ai également constaté que lorsque nous imprimons au format PDF une page avec des graphiques SVG, le PDF résultant contient toujours une image vectorielle, tandis que si vous imprimez une page avec des graphiques Canvas, l'image du fichier PDF résultant est pixellisée.

ostrokach
la source