2017-01-09 3 views
1

Je souhaite créer une chronologie dans laquelle l'utilisateur peut choisir entre un défilement pour zoomer ou une région à zoomer. Il y a quelques exemples de la première: comme https://bl.ocks.org/mbostock/4015254 ou le zoom sur une zone avec une brosse: https://bl.ocks.org/mbostock/f48fcdb929a620ed97877e4678ab15e6
Mais je ne peux pas trouver un exemple qui fait les deux. Comment puis-je faire les deux? Ou y a-t-il des exemples que j'ai manqués?Timeline brushable et zoomable avec d3

+0

Est-ce que mon commentaire ci-dessous m'a aidé? – HamsterHuey

+0

Non, je n'ai pas pu l'implémenter. Mais en ce moment je me concentre sur mes examens, donc je n'ai pas le temps de passer plus d'une journée dessus. –

Répondre

0

Ce n'est pas la chose la plus simple à mettre en œuvre. Comme vous le remarquerez, le zoom basé sur le pinceau ne repose pas sur d3.zoom mais effectue plutôt le zoom via les écouteurs qui déclenchent les événements pour faire tout ce qui est nécessaire pour redimensionner les axes et déplacer les éléments de tracé en conséquence.

En comparaison, tous les exemples de zoom en fonction de défilement se fondent généralement sur d3.zoom qui utilise un comportement d3.zoom() qui garde la trace de toutes les transformations effectuées sur le terrain en mode panoramique/zoom et est seul responsable de la mise à jour des différents éléments du graphique. La difficulté réside dans le fait que les deux approches sont très différentes et si vous modifiez manuellement la vue graphique via le brossage, vous devez trouver un moyen de mettre à jour la transformation de zoom interne que les références d3.zoom afin qu'il soit conscient des changements effectués via les événements de zoom basés sur la brosse.

Ce n'est pas du tout facile à faire car d3.zoom n'a pas été conçu pour recevoir des informations provenant d'ailleurs et l'enregistrement interne des transformations effectuées ne doit pas être mis à jour/mutable. Vous pouvez mettre à jour la transformation via selection.call(zoom.transform, d3.zoomIdentity); mais cela déclenche malheureusement tout un tas d'événements liés au comportement de zoom réel, ce qui n'est pas quelque chose que vous voulez puisque vous avez déjà géré tout le comportement du zoom avec votre zoom basé sur le pinceau. Une solution de contournement laid, mais efficace que j'ai pu utiliser pour réinitialiser le zoom transformer était de muter le champ .__zoom réel du noeud DOM qui est lié au comportement d3.zoom comme suit:

// WARNING: Ugly mutation of __zoom property of pan/scroll-zoom rect to 
// reset the transform without having to fire events associated with zoom 
// d3.select(".zoom").node().__zoom = {k: 1, x: 0, y: 0}; <-- Fails since __zoom contains other hidden objects 
scrollZoom.node().__zoom["k"] = 1; 
scrollZoom.node().__zoom["x"] = 0; 
scrollZoom.node().__zoom["y"] = 0; 

Ainsi, par exemple: Si vous voulez un pinceau 2D pour le zoom rectangle, mais aussi d3.zoom zoom basé pour le panoramique et le défilement de la souris, puis à chaque fois que vous utilisez le pinceau 2D pour zoomer, vous devez réinitialiser la transformation d3.zoom à la transformation d'identité comme ci-dessus. Cela évite et gêne la gigue dans la réponse de panoramique/défilement lorsque vous enchaînez des actions de zoom basées sur un pinceau 2D avec des actions de défilement/souris en raison de la transformation en enregistrement avec d3.zoom n'étant pas synchronisé avec la vue affichée (grâce au pinceau 2D) zoom basé modifiant la vue sans la connaissance de d3.zoom).

Voici quelque chose d'autre qui est important de noter:

d3.zoom a une limitation en ce qu'elle soutient actuellement seulement une échelle de zoom commun pour les axes X et Y (Source). Cela signifie malheureusement qu'il n'y a aucun moyen de mapper un zoom basé sur un pinceau 2D à une approche basée sur d3.zoom puisque le zoom basé sur un pinceau 2D produit une mise à l'échelle du zoom différente en X et Y. Si vous voulez faire les choses avec un minimum de problèmes, , Je recommande d'examiner en utilisant d3.xyzoom. Ceci est un fork de d3.zoom qui implémente le support pour différentes échelles pour les axes X et Y. Cela vous permet de calculer les valeurs de mise à l'échelle et de translation du zoom X et Y correspondantes pour toute sélection de pinceau 2D, que vous pouvez ensuite ajouter à d3.zoom, ce qui vous permet d'effectuer tout le zoom en utilisant une approche commune. de duplication de code). Cela étant dit, si vous êtes uniquement intéressé par un zoom basé sur un pinceau 1-D, vous devriez être capable de mapper cela à un d3.zoom approche afin que vous n'avez pas à faire face à 2 chemins différents pour gérer la vue et la mise à l'échelle de tous les axes et autres éléments graphiques dans votre tableau. Voici un bon exemple:

https://bl.ocks.org/mbostock/34f08d5e11952a80609169b7917d4172

Je présente mes excuses pour la durée de ce poste et si elle est un peu décousu. Je travaille sur la mise en place d'un bloc sur mon travail dans quelques jours et je vais essayer de revenir en arrière ici et afficher un lien quand je me déplace pour le faire. J'ai seulement commencé à apprendre le D3 il y a une semaine, donc j'apprends en cours de route.