D3 - How to get correct scale and translate origin after manual zoom and pan to country path

bcm picture bcm · Dec 19, 2013 · Viewed 8.2k times · Source

I've got a topology map with pan and zoom functionality.

Clicking on the country, I'm zoom/panning into the country, using this:

  if (this.active === d) return

  var g = this.vis.select('g')
  g.selectAll(".active").classed("active", false)
  d3.select(path).classed('active', active = d)

  var b = this.path.bounds(d);
  g.transition().duration(750).attr("transform","translate(" +
    this.proj.translate() + ")" +
    "scale(" + .95 / Math.max((b[1][0] - b[0][0]) / this.options.width, (b[1][1] - b[0][1]) / this.options.height) + ")" +
    "translate(" + -(b[1][0] + b[0][0]) / 2 + "," + -(b[1][1] + b[0][1]) / 2 + ")");

  g.selectAll('path')
    .style("stroke-width", 1 / this.zoom.scale())

However, if I continue to drag pan, the map jerks back into the initial position before the click happens, before panning. Code to pan/zoom is here:

  this.zoom = d3.behavior.zoom().on('zoom', redraw)
  function redraw() {

    console.log('redraw')

    _this.vis.select('g').attr("transform","translate(" +
      d3.event.translate.join(",") + ")scale(" + d3.event.scale + ")")

    _this.vis.select('g').selectAll('path')
      .style("stroke-width", 1 / _this.zoom.scale())
  }
  this.vis.call(this.zoom)

In another words, after zooming into a point by clicking, and then dragging by the redraw function, the redraw does not pick up the correct translate+scale to continue from.

Answer

bcm picture bcm · Dec 19, 2013

To continue at the right 'zoom' after the transition, I had to set the zoom to the new translate and scale.

Example of reset which is applied similarly to my click and zoom event, the set new zoom point is the critical bit:

_this.vis.select('g').transition().duration(1000)
   .attr('transform', "translate(0,0)scale(1)")

/* SET NEW ZOOM POINT */
_this.zoom.scale(1);
_this.zoom.translate([0, 0]);