javascript - d3.js: Priblíženie pri kliknutí


Snažil som sa dosiahnuť rovnaké správanie ako implementácia Wil Linssen, ale na verzii d3.js 4. Som dosť zmätený z API zoom v verzii 4.

Zmeny, ktoré som urobil v pôvodnej implementácii, sú: zoom.translate() nahradené d3.zoomTransform(selection.node()) a pridané príslušné body takto:

svg.attr("transform",
    "translate(" + t.x + "," + t.y + ")" +
    "scale(" + t.k + ")"
);

Tento:

zoom
  .scale(iScale(t))
  .translate(iTranslate(t));

nahradené na

var foo = iTranslate(t);
zoom.
  translateBy(selection, foo[0], foo[1]);
zoom
  .scaleBy(selection, iScale(t));

Ale stále to má problém, vyzerá to, že s mierkou, priblížiť, oddialiť...

Príklad: Príklad na d3.v4 - jsfiddle

Ďakujem za pomoc

Odpoveď č. 1

Po preskúmaní najjednoduchšieho spôsobu použitia d3 v4 API, ktoré poskytuje interpoláciu a podobne hneď po vybalení. V pôvodnej otázke bolo zväčšovanie implementované od nuly, čo v verzii 4 nedáva zmysel. Riešenie je podobné odpovediam @Nixie a obsahuje len niekoľko riadkov kódu.

Táto verzia zahŕňa aj posúvanie, ak to nepotrebujete, odstráňte svg.call(zoom);

Konečný príklad: Zoom D3 v4 - jsfiddle

Jedna zaujímavá poznámka: Funkcia:

function transition() {
  svg.transition()
      .delay(100)
      .duration(700)
      .call(zoom.scaleTo, zoomLevel);
      //.on("end", function() { canvas.call(transition); });
}

call(zoom.ScaleTo, zoomLevel) - priblíži na stred stránky. Ak však potrebujete stred obrázka, použite toto: call(zoom.transform, transform);

Kde transform je funkcia, ktorá nastavuje stred vášho obrázka. Príklad takejto funkcie:

function transform() {
  return d3.zoomIdentity
      .translate(width / 2.75, height / 2.75)
      .scale(zoomLevel)
      .translate(-width/2.75, -height/2.75);
}

Odpoveď č. 2

Tento kus kódu nevyrieši všetky problémy, ale môže byť východiskovým bodom. V D3 v4 môžete prechod zväčšenia vykonať v jednom riadku kódu (pozrite si tiež https://github.com/d3/d3-zoom/blob/master/README.md#zoom_transform)

function interpolateZoom (translate, scale) {
    return selection.transition().duration(350)
              .call(zoom.transform, 
                    d3.zoomIdentity.translate(translate[0], translate[1]).scale(scale))
}

Upravený príklad: https://jsfiddle.net/2yx1cLrq/. Tiež je potrebné nahradiť selection s selection.node() vo všetkých volaniach d3.zoomTransform