En utilisant D3, le zoom sémantique peut-il être appliqué à un arbre radial?

J'utilise l' arbre de lien du noeud D3, et j'ai du mal à essayer d'obtenir un zoom sémantique.

J'ai déjà passé un peu de temps, essayant de le faire fonctionner, alors je pensais que je demanderais ici, pour voir si cela est possible avant de passer plus de temps … Je ne sais pas si le zoom sémantique est linéaire C'est juste une sorte de chose.

Edit – Solution de travail

Voici ma solution de travail. Je n'ai pas nettoyé le code ici, mais ça devrait vous donner une idée.

En raison de la manière différente dx et dy sont interprétées dans l'arbre radial, l'approche simple "zoom sémantique", où vous laissez l'objet de comportement et les échelles effectuer tous les calculs, ne fonctionne pas.

Les coordonnées (x, y) calculées par l'arborescence sont utilisées pour tracer les angles et la distance du centre dans un arbre radial. Ces valeurs ne se transforment pas directement en coordonnées x et y que crée le comportement de zoom. Ainsi, vous ne pouvez pas simplement attacher vos échelles à votre comportement de zoom, faire modifier le champ d'échelle automatiquement sur le zoom, puis replacer vos points à l'aide des balances.

(PS Je suppose que vous voulez juste un zoom normal pour agrandir une partie du graphique, et pas un nouveau calcul d'angles comme l'exemple de Sunburst zoom zoom Jason Davies.)

Un récapitulatif de la façon dont vos éléments sont transformés pour la mise en page initiale:

  • Une traduction sur l'élément <g> qui contient le graphique positionne la coordonnée (0,0) au centre de la zone de traçage.

  • Une rotation sur chaque groupe de noeuds, calculée en fonction de la valeur dx partir de la mise en page (toujours entre 0 et 360), définit l'angle.

  • Et puis (l'ordre est important), une traduction sur chaque groupe de noeud le déplace loin du centre, le long de la ligne de base tournée, selon la valeur dy de la disposition qui est mise à l'échelle en fonction du rayon désiré du cercle.

Notez que l'exemple de l'arbre radial fait toute la mise à l'échelle dans la fonction de mise en page de l'arborescence (en appelant la méthode size() ) – aucune échelle n'est utilisée.

Afin de zoomer sur une section du cercle, vous devrez:

  • Traduisez le centre de la mise en page vers un autre endroit que le centre du tracé en appliquant une transformation à l'élément <g> .

  • Soit Modifiez l'échelle de l'image entière (cela augmentera également le texte, la taille du cercle, etc.) avec une deuxième transformation sur l'élément <g>

  • Ou modifier la traduction horizontale de chaque noeud selon le facteur d'échelle.

Notez que vous laissez l'angle de rotation des noeuds seul!

Si vous n'affectez pas la mise à l'échelle du texte et la taille de vos nœuds, appliquer les transformations à l'élément <g> est assez simple.

Si vous souhaitez zoomer sur la mise en page sans augmenter la taille des éléments individuels, vous devrez changer la façon dont la distance du centre de la mise en page est calculée.

Pour obtenir la traduction du centre correcte:

  • Dans votre fonction de zoom, utilisez d3.event.translate pour accéder au tableau (x, y) de la traduction souhaitée pour l'ensemble du graphique.

  • Utilisez ceci pour survoler la transformation sur l'élément <g> , en rappelant que pour une traduction de zoom de (0,0), vous souhaitez toujours que l'élément <g> ait une traduction de (largeur / 2, hauteur / 2). Donc vous avez besoin de quelque chose comme:

    svg.attr("transform", "translate(" + (width/2 + d3.event.translate[0]) +
    "," + (height/2 + d3.event.translate[1]) + ")" );

  • Si vous envisagez d'étendre l'élément <g> directement, vous devriez définir les deux transformations dans le même appel d'attribut, en tant que chaîne longue, et vous voudriez faire des tests pour voir si cela fonctionnait plus naturellement pour appliquer l'échelle Avant ou après la traduction ( scale(2) translate(50) est égal à la version translate(100) scale(2) , car les coordonnées de la traduction sont également mises à l'échelle). Le facteur d'échelle est disponible sous la forme d3.event.scale .

Pour obtenir la mise à l'échelle de la distance du centre (variable "y") correcte:

  • Créez une échelle radiale avec le domaine [0,1] et la plage [0,radius] .

  • Définissez la taille de l'arborescence pour avoir "hauteur" de 1 au lieu d'utiliser le rayon directement.

  • Lorsque vous positionnez vos noeuds, utilisez la balance pour convertir la valeur dy de la disposition (qui sera entre 0 et 1) dans la distance radiale réelle utilisée dans la transformation.

    node.attr("transform", function(d) { return "rotate(" + (dx - 90)
    + ")translate(" + radialScale(dy) + ")"; })

  • Sur votre comportement de zoom, n'ajoute aucune balance! Bien que vous deviez ajuster l'échelle radiale en fonction du zoom, vous souhaitez seulement ajuster l'échelle et ne pas la traduire également – toutes les traductions seront appliquées directement à l'élément <g> qui définit le centre du cercle.

  • Dans votre fonction de zoom, définissez le domaine de l'échelle radiale sur [0, 1/d3.event.scale] . En d'autres termes, si le comportement du zoom nous dit d'agrandir l'image par 2, nous voulons la distance entre le centre et le bord de la zone de traçage (la plage que vous ne changez pas) pour représenter 1/2 la distance entre le Au centre et au bord de l'arbre (le domaine).

  • Ensuite, réinitialisez l'attribut de transformation sur les groupes de noeuds individuels en utilisant la même syntaxe que ci-dessus. (Vous voudrez que cette fonction anonyme soit nommée afin que vous puissiez simplement passer le nom de la fonction dans les deux parties de votre code.)

Donc, je ne sais pas si tout ce code supplémentaire compte plus comme "zoom sémantique". Mais il devrait faire un zoom sur votre graphique. Si vous travaillez, travaillez et revenez et laissez un lien!