Skip to content Skip to sidebar Skip to footer

Get Mouse Position In Svg Co-ordinates After Zoom

Using D3 v4, SVG, and the zoom behaviour, on mousemove, I want to display the mouse co-ordinates in SVG's co-ordinate system. The mousemove event only appears to provide client/scr

Solution 1:

In order to convert the coordinate returned by d3.mouse to the coordinate system used by d3.zoom, you need to get the zoom transform in addition to the coordinates returned by d3.mouse. I'll highlight one method here.

You can get the current zoom transform with:

d3.zoomTransform(selection.node());

Where selection is the d3 selection the zoom is called on. While d3.mouse() gives us the screen coordinates of the mouse relative to the container, we can use that and the transform to give us the scaled and translated coordinates with transform.invert(), which takes a point and will return the zoomed coordinates:

var xy = d3.mouse(this);         // relative to specified containervar transform = d3.zoomTransform(selection.node());
  var xy1 = transform.invert(xy);  // relative to zoom

Here's a quick example showing extraction of the zoomed coordinates as compared with the mouse coordinates. The axes are just to give a rough idea of what the zoom coordinate system is (they show zoom coordinates), but the functionality remains the same without them:

var svg = d3.select("body")
  .append("svg")
  .attr("width", 500)
  .attr("height", 300)
  .attr("fill","#eee");
  
var g = svg.append("g")
  .attr("transform","translate(50,50)");
  
var rect = g.append("rect")
  .attr("width",400)
  .attr("height",200)
  .attr("fill","#eee");

var x = d3.scaleLinear().domain([0,400]).range([0,400]);
var y = d3.scaleLinear().domain([0,200]).range([0,200]);

var axisX = d3.axisTop().scale(x).tickSize(-200)
var axisY = d3.axisLeft().scale(y).tickSize(-400);

var gX = g.append("g").call(axisX)
var gY = g.append("g").call(axisY)

var zoom = d3.zoom()
  .scaleExtent([1, 8])
  .on("zoom",zoomed);
  
rect.call(zoom);

rect.on("click", function() {
  var xy = d3.mouse(this);
  
  var transform = d3.zoomTransform(rect.node());
  var xy1 = transform.invert(xy);

  console.log("Mouse:[", xy[0], xy[1], "] Zoomed:[",xy1[0],xy1[1],"]")
})
  
functionzoomed() {
  gX.call(axisX.scale(d3.event.transform.rescaleX(x)));
  gY.call(axisY.scale(d3.event.transform.rescaleY(y)));
}
rect {
  cursor: pointer;
}
.tick line {
  stroke: #ccc;
  pointer-events: none;
}
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>

Of course you must ensure that d3.mouse and d3.zoom are referencing the same thing, in this case the rectangle.

Post a Comment for "Get Mouse Position In Svg Co-ordinates After Zoom"