如何将相对于元素定义的SVG坐标(x,y)转换为绝对坐标/位置?

5
我正在尝试在SVG中绘制一条连接两个圆的线。这些圆 - 连同底层矩形一起封装在SVG组元素()中。这些组使用transform="translate(x,y)"属性定位。
我的问题是,组内元素的坐标相对于它们所在组的原点(0,0坐标)定位。为了放置重叠的线条,我需要知道绝对坐标。
以下是使用D3 JavaScript库的代码:
var body = d3.select("body");

var svg = body.append("svg");

var group1 = svg.append("g")
    .attr("transform", "translate(50,50)");

var rect1 = group1.append("svg:rect")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 100)
    .attr("height", 100)
    .style("fill", 'lightblue');

var circ1 = group1.append("svg:circle")
    .attr("cx", 50)
    .attr("cy", 50)
    .attr("r", 10)
    .style("fill", 'red')

var group2 = svg.append("g")
    .attr("transform", "translate(350,50)");

var rect2 = group2.append("svg:rect")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 100)
    .attr("height", 100)
    .style("fill", 'lightgreen');

var circ2 = group2.append("svg:circle")
    .attr("cx", 50)
    .attr("cy", 50)
    .attr("r", 10)
    .style("fill", 'red');

var line = svg.append("svg:line")
    .attr("x1", parseInt(circ1.attr("cx")))
    .attr("y1", parseInt(circ1.attr("cy")))
    .attr("x2", parseInt(circ2.attr("cx")))
    .attr("y2", parseInt(circ2.attr("cy")))
    .attr("stroke", "black");

我知道为什么线条没有出现。我也知道每个SVG元素都与一个变换矩阵相关联。我不确定如何访问圆形元素的矩阵,以及如何获得它们的绝对坐标(cx/cy属性)。另一种可能性是获取圆的绝对距离。
这里有一个包含上述代码的jsfiddle

如果您将元素保持在同一组中,那么这将变得更加容易。 - Lars Kotthoff
1
是的,它会。但是我必须手动处理圆形和矩形的位置。这就是为什么我决定尝试使用多个组的方法的原因。 - karlitos
1个回答

6

我认为我已经能够自己解决这个问题。可以使用以下方式访问转换矩阵:

circ1[0][0].getCTM()

或通过使用

circ1[0][0].getScreenCTM()

通过将 e 属性的值添加到 x 坐标和 f 属性的值添加到 y 坐标,我能够获得元素的“绝对位置”。

更新后的 jsfiddle 在 这里

恐怕我的解决方案不是普遍适用的。例如,在计算位置之前使用 transform:scale,我不确定会发生什么情况?


你让我朝着正确的方向前进了。我认为阅读并理解SVG文档的第7章将会给我整个故事。我假设首选方法是使用变换矩阵和各种像矩阵乘法这样的东西来实现你(和我)正在尝试做的事情。 - pedz
1
我认为你可以使用从这里获取的完整公式,将一个新的坐标系映射到 https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform; absX = ax + cy + e 和 absY = bx + dy + f(在转换平移的情况下,将简化为您当前答案中的解决方案)。 - Alex G
顺便说一下,只有 getScreenCTM 对我返回有效数据。从 getCTM 获取的矩阵在应用后不会改变位置。 - Alex G

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接