Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3.js: Zoom on click event

I was trying to get same behavior Wil Linssen's implementation but on d3.js version 4. I am quite confused with zoom api in version 4.

The changes that I made in the original implementation is: zoom.translate() replaced with d3.zoomTransform(selection.node()) and appropriate points added instead:

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

This one:

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

replaced to

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

But it's still has a problem, looks like with scale, zoom out...

Example: Example on d3.v4 - jsfiddle

Thanks for the help

like image 933
Vladyslav Babenko Avatar asked Oct 08 '16 12:10

Vladyslav Babenko


2 Answers

After researching the most easiest way to use d3 v4 api that provides interpolation etc out of box. In original question zoom implemented from scratch, that doesn't make sense in version 4. Solution is similar to @Nixie answers and has few lines of code.

This version includes pan as well, if you do not need, remove svg.call(zoom);

Final example: Zoom D3 v4 - jsfiddle

One interesting note: The function:

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

call(zoom.ScaleTo, zoomLevel) - will zoom to the center of page. But if you need the center of an image, use this one: call(zoom.transform, transform);

Where transform is a function that sets center of your image. For example of such function:

function transform() {
  return d3.zoomIdentity
      .translate(width / 2.75, height / 2.75)
      .scale(zoomLevel)
      .translate(-width/2.75, -height/2.75);
}
like image 71
Vladyslav Babenko Avatar answered Oct 23 '22 11:10

Vladyslav Babenko


This piece of code does not resolve all the problems, but could be a starting point. In D3 v4 you can transition zoom in one line of code (see also 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))
}

Modified example: https://jsfiddle.net/2yx1cLrq/. Also, you need to replace selection with selection.node() in all calls to d3.zoomTransform

like image 23
Nixie Avatar answered Oct 23 '22 11:10

Nixie