0

I try to make an orgchart with zoom and paning. To do so I need to call .nodeSize which translate my "root" to (0,0). Then I re-translate it by width/2 and it's ok. But when I implement d3.zoom, my "root" go back to (0,0)... How can i avoid this behavior ?

Here is the code concerned :

var svg = d3.select("#svg1").append("svg")
  .attr("width", width)
  .attr("height", height)
  .call(d3.zoom().on("zoom", function () {
  svg.attr("transform", d3.event.transform);
  }))
  .append('g').attr("transform","translate(" + width / 2 + "," + 0 + ")");

Thanks for reading.

EDIT : I did a JSFiddle so you can try my current code. Don't pay attention to big traingles (I don't have them on my real project) => https://jsfiddle.net/rhz1n8m4/12/

Zoom
  • 5
  • 3

2 Answers2

1

You can use zoom.transform() to set the initial translation of the zoom.

You can also check this Stackoverflow thread for a usage example. So in your case, you would do

var svg = d3.select("#svg1").append("svg")
    .attr("width", width)
    .attr("height", height)
    .call(d3.zoom().on("zoom", function () {
        svg.attr("transform", d3.event.transform);
    }))
  .call(d3.zoom().transform, d3.zoomIdentity.translate(width / 2, 0))
  .append("g").attr("transform","translate(" + width / 2 + "," + 0 + ")");
0

Apply the zoom to a node below the width/2 transform.

Rename your vars to reflect what they contain: svg does not contain the svg element.

var svg = d3.select("#svg1").append("svg")
.attr("width", width)
.attr("height", height)
.call(d3.zoom().on("zoom", function () { svg.attr("transform", d3.event.transform); }))
.append('g').attr("transform","translate(" + width / 2 + "," + 0 + ")")
.append('g');

Edit

@Zoom proposed a solution with transform-origin (see edit history), clearly a workaround. Better is to re-arrange the g elements.

Apply the zoom to a node above the width/2 transform.

  var svg1 = d3.select("#svg1")
    .append("svg")
      .attr("width", width)
      .attr("height", height)
    .call(d3.zoom().on("zoom", function () { svg1.attr("transform", d3.event.transform); }))
    .append('g');
  var svg = svg1.append('g')
      .attr("transform","translate(" + width / 2 + "," + 0 + ")");

Read the d3-zoom doc page and you might find a different solution that does not use a transform attribute.

rioV8
  • 24,506
  • 3
  • 32
  • 49
  • THANK YOU! It works, I will analyse carefully why, I'm totally new to JavaScript AND D3. Thank you again for your time and your answer ! – Zoom Nov 08 '18 at 12:02
  • Just to be complete, this works BUT the center of the zoom seems to be translated by width/2 now. I will inestigate ! – Zoom Nov 08 '18 at 12:07
  • The answer had been edited, adding ".style("transform-origin", "-50% 0 0")" fix zoom issues. 100% working now – Zoom Nov 15 '18 at 15:46
  • @Zoom: there is a much more elegant solution to this initial translate problem. – rioV8 Nov 15 '18 at 15:52
  • It's more than possible indeed ^^ I did with my few knowledge. What is this solution ? – Zoom Nov 15 '18 at 16:01
  • Indeed ! Thank you very much, my method was really ugly ^^ (and I knew it) – Zoom Nov 19 '18 at 14:03