缩放后获取鼠标在SVG坐标中的位置

426

在mousemove上,使用D3 v4,SVG和缩放行为,我想在SVG的坐标系中显示鼠标坐标。

mousemove事件仅显示为提供客户端/屏幕坐标。

如何将这些坐标转换为反映当前Zooom / pan / etc转换的SVG坐标?

我可以使用axis / scales / etc看到这样的示例,但是我没有创建图形,也没有使用axis / etc-我使用D3.js绘制交互式图表。

我已经尝试过crateSVGPoint / getScreenCTM方法,但是(a)不太了解它,因此不确定如何将其应用到我的代码中;(b)缩放/平移时它似乎不起作用-我只是获取客户/屏幕坐标。EG:这是我的mousemove事件中转换为SVG坐标的代码:

var theSvg = document.getElementById('svgItem');
var pt = theSvg.createSVGPoint();
var cursorPoint = function(evt){
  pt.x = evt.clientX; pt.y = evt.clientY;
  return pt.matrixTransform(theSvg.getScreenCTM().inverse());
}
var loc = cursorPoint(d3.event);

//the pair of co-ordinates should be different on zoom, but aren't
d3.select(".statusBarText").text("move (" + d3.event.x + "," + d3.event.y + ") (" + loc.x + "," + loc.y + ")");

出于价值考虑,缩放行为将应用于SVG元素的SVG组元素。缩放效果很好;我可以看到平移/缩放应用于该组。

我试图修改上面的内容,以对已转换的group元素调用createSVGPoint(),但会收到有关createSVGPoint()不是函数的错误;我猜这只适用于DOM中的SVG元素...

我正在使用的SVG元素上还有一个viewBox设置,如果有区别的话。

当然,必须有一种简单的方法来进行转换吗?

安德鲁·里德(Andrew Reid)

为了将d3.mouse返回的坐标转换为d3.zoom使用的坐标系,除了d3.mouse返回的坐标外,还需要进行缩放转换。我将在这里重点介绍一种方法。

您可以使用以下方法获取当前的缩放变换:

d3.zoomTransform(selection.node());

在选择是d3选择的情况下,将调用缩放。虽然d3.mouse()为我们提供了鼠标相对于容器的屏幕坐标,但是我们可以使用它和transform通过给出缩放和转换后的坐标transform.invert(),该坐标将获得一个点并返回缩放后的坐标:

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

这是一个简单的示例,显示了与鼠标坐标相比提取的缩放坐标。轴只是为了大致了解缩放坐标系(它们显示缩放坐标),但是如果没有它们,功能将保持不变:

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],"]")
})
  
function zoomed() {
  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;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>

当然,您必须确保d3.mouse和d3.zoom引用同一对象,在本例中为矩形。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章