use*_*445 4 javascript svg zooming d3.js
使用 D3 v4、SVG 和缩放行为,在 mousemove 上,我想在 SVG 坐标系中显示鼠标坐标。
mousemove 事件似乎仅提供客户端/屏幕坐标。
如何将这些坐标转换为反映当前缩放/平移/等变换的 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 + ")");
Run Code Online (Sandbox Code Playgroud)
无论如何,缩放行为应用于 SVG 元素的 SVG 组元素。缩放效果很好;我可以看到平移/缩放应用于该组。
我尝试修改上面的内容以在已转换的组元素上调用 createSVGPoint() ,但收到有关 createSVGPoint() 不是函数的错误;我猜这只适用于 DOM 中的 SVG 元素...
我正在使用的 SVG 元素上还设置了一个 viewBox(如果这有影响的话)。
当然必须有一种简单的方法来进行转换吗?
为了将 d3.mouse 返回的坐标转换为 d3.zoom 使用的坐标系,除了 d3.mouse 返回的坐标之外,还需要获取缩放变换。我将在这里重点介绍一种方法。
您可以通过以下方式获取当前的缩放变换:
d3.zoomTransform(selection.node());
Run Code Online (Sandbox Code Playgroud)
其中,selection 是调用缩放的 d3 选择。虽然 d3.mouse() 为我们提供了鼠标相对于容器的屏幕坐标,但我们可以使用它和转换来为我们提供缩放和平移坐标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
Run Code Online (Sandbox Code Playgroud)
这是一个简单的示例,显示了与鼠标坐标相比的缩放坐标的提取。这些轴只是为了粗略地了解缩放坐标系是什么(它们显示缩放坐标),但没有它们功能仍然相同:
d3.zoomTransform(selection.node());
Run Code Online (Sandbox Code Playgroud)
var xy = d3.mouse(this); // relative to specified container
var transform = d3.zoomTransform(selection.node());
var xy1 = transform.invert(xy); // relative to zoom
Run Code Online (Sandbox Code Playgroud)
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)));
}Run Code Online (Sandbox Code Playgroud)
当然,您必须确保 d3.mouse 和 d3.zoom 引用相同的事物,在本例中为矩形。