web-dev-qa-db-fra.com

exemple de réécriture du zoom de d3.js dans la version 4

Exemple de glisser-déposer

J'essaie de réécrire une partie de cet exemple ci-dessus pour l'utiliser dans mon code, en particulier cette pièce:

function centerNode(source) {
        scale = zoomListener.scale();
        x = -source.y0;
        y = -source.x0;
        x = x * scale + viewerWidth / 2;
        y = y * scale + viewerHeight / 2;
        d3.select('g').transition()
            .duration(duration)
            .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")");
        zoomListener.scale(scale);
        zoomListener.translate([x, y]);
    }

Cependant, je suis bloqué depuis que le paquet v4 a pas mal changé. J'ai écrit ma fonction zoomListener pour être

    var zoomListener = d3.zoom()
                 .scaleExtent([0.3,2])
                 .on("zoom", zoomed);

    function zoomed() {
       transform = d3.event.transform;
       console.log(d3.event);
         svg.attr("transform", transform);
    } 

function centerNode(source){
  t = transform;
  console.log(t);
  x = t.x*t.k; //I only want things to be centered vertically
  y = (t.y + -source.x0)*t.k + (viewerHeight)/2 ;
  svg.transition()
     .duration(duration)
     .attr("transform","translate(" + x + "," + y +")scale(" + t.k + ")");

  transform.scale(t.k); //DOES NOT WORK
  transform.translate([x, y]); //DOES NOT WORK

}

et je sais que, selon la doc, les choses ont changé et que les informations ne sont plus stockées sur ce que serait mon zoomListener Note de version D3 V4 sur le zoom Je suppose que je ne comprends pas comment je suis censé faire avec la nouvelle version. Les dernières lignes de ma fonction centerNode ne fonctionnent pas, ce qui a pour effet de réinitialiser le zoom et le panoramique lorsque je centre le noeud ...

Toute suggestion?

13
Tekill

Donc, après beaucoup de recherches et d’essais et d’erreur, j’ai trouvé une réponse qui convient assez bien à mes fins. Notez que ce code ci-dessous est seulement la partie pertinente de mon code, pas tout le code, certaines variables étaient explicites et ne les incluaient pas. AUSSI CE IS DANS LA VERSION 4 de d3.js.

var zoom = d3.zoom()
             .scaleExtent([0.3,2])
             .on("zoom", zoomed);


var svg = d3.select("body")
            .append("svg")
              .attr("width", viewerWidth)
              .attr("height", viewerHeight);

var zoomer = svg.append("rect")
                .attr("width", viewerWidth)
                .attr("height", viewerHeight)
                .style("fill", "none")
                .style("pointer-events", "all")
                .call(zoom);

var g = svg.append("g");

zoomer.call(zoom.transform, d3.zoomIdentity.translate(150,0)); //This is to pad my svg by a 150px on the left hand side

function zoomed() {
  g.attr("transform", d3.event.transform);//The zoom and panning is affecting my G element which is a child of SVG
}

function centerNode(source){

  t = d3.zoomTransform(zoomer.node());
  console.log(t);

  x =  t.x;
  y = source.x0;

  y = -y *t.k + viewerHeight / 2;

  g.transition()
   .duration(duration)
   .attr("transform", "translate(" + x + "," + y + ")scale(" + t.k + ")")
   .on("end", function(){ zoomer.call(zoom.transform, d3.zoomIdentity.translate(x,y).scale(t.k))});


}

Selon les exemples pour v4 de la page d3.js, j’ai utilisé un rectangle pour appliquer le zoom sur 

Le comportement de zoom est appliqué à un rect invisible superposant le SVG élément; cela garantit qu'il reçoit une entrée et que le pointeur les coordonnées ne sont pas affectées par la transformation du comportement de zoom. Exemple de panoramique et zoom

Dans la fonction de noeud Centre, j'utilise d3.zoomTransform(zoomer.node()); pour obtenir la transformation actuelle appliquée à la page. Le but de cette fonction est seulement de centrer l’arborescence pliable verticalement et non horizontalement, je garde donc la transformation actuelle.x (ici t.x) la même . Les coordonnées dans mon svg sont des flip, d’où pourquoi y= source.x0, source est un noeud sur lequel l'utilisateur a cliqué dans mon arbre compressible. ("Regardez dans l'exemple référencé en haut de ce fil pour comprendre ce que je tente de convertir en version 4)

J'applique la transformation à mon élément G, puis je souhaite appliquer ces modifications à la transformation de zoom. Pour ce faire, j'utilise la méthode .on("end", function(){}), sinon le comportement était étrange avec la transition. de la transformation.

zoomer.call(zoom.transform, d3.zoomIdentity.translate(x,y).scale(t.k))

La ligne ci-dessus applique une traduction de x et y et une échelle - égale à celle de l'état actuel - à la matrice d'identification qui doit obtenir une nouvelle transformation pour G, puis je l'applique à zoomer qui est l'élément I appelé zoom plus tôt.

Cela a fonctionné comme un charme pour moi!

17
Tekill

L'appel de transform.scale et transform.translate renvoie une nouvelle transformation et ne modifie rien. Donc:

transform = transform.translate([x, y]).scale(k)

svg.call(zoomListener.transform, newTransform)

(À ce stade, zoomListener est un nom assez imprécis pour cela, mais peu importe ...)

k, x et y peuvent être dérivés de source, peut-être comme vous le montrez, mais je ne suis pas sûr, car je ne sais pas ce que source est. Mais pour moi, t.x*t.k a l'air suspect, car il multiplie les transformations existantes x par son échelle. On dirait que cela provoquerait une boucle de rétroaction.

Pour en savoir plus sur le zoom dans v4, consultez cet article StackOverflow associé ou cet exemple de mbostock démontrant le contrôle par programme de la transformation du zoom d'un élément (la toile dans ce cas) et inclut les transitions.

0
meetamit