我有一点烦人的问题。
我正在尝试根据一组具有相似属性的现有 SVG 文本元素来定位一组 SVG 圆形元素。
圆形元素是在与文本元素完全不同的过程中创建的,因此仅使用与旧元素相同的变换等来定位新元素不是一个可行的选择。
我正在尝试使用 .getBoundingClientRect() 来获取位置,因为文本元素被转换为位置(因此 .getBBox() 不是一个选项)而不是由 x 和 y 属性定位。
使用 .getBoundingClientRect(),我可以获得新元素的正确大小/排列,但是由于包含 svg 的 div 的宽度是可变的,所以总是有一些我无法完全解释的奇怪偏移为。
我为我的问题创建了一个简化示例 here .调整页面大小并刷新页面以查看实际问题。
下面复制了我用来定位圆形元素的代码。
var circs = theSvg.selectAll("circle")
.data(theCircles)
.enter()
.append("circle")
.attr("r", 15)
.attr("fill", "#f00")
.style("opacity", 0.3)
.attr("transform", function(d){
var sizeDif = 800/(d3.select(".svgTestHolder")[0][0].getBoundingClientRect()["width"]);
var theNum = parseInt(d.split("&")[1]);
var thePosition = theSvg.selectAll("text").filter(function(e){
return e == theNum;})[0];
var theCoords = thePosition[0].getBoundingClientRect();
var leftOffset = d3.select(".svgTestHolder")[0][0].getBoundingClientRect()["left"];
var leftOffset2 = d3.select(".svgTest")[0][0].getBoundingClientRect()["left"];
var bottomOffset = d3.select(".svgTestHolder")[0][0].getBoundingClientRect()["top"];
var bottomOffset2 = d3.select(".svgTest")[0][0].getBoundingClientRect()["top"];
return
"translate(" + ((theCoords["left"] - leftOffset - leftOffset2)
* sizeDif) + "," + ((theCoords["top"] - bottomOffset - bottomOffset2)
* sizeDif) + ")";
})
编辑:
这是一个非常延迟的更新,只是为了说明虽然我无法按照所述回答我的问题,但我能够根据 Paul LeBeau 的建议制定一个可行的解决方案以从目标元素中提取转换。
在我的例子中,我不得不使用一系列连续的转换,而不是转换和改变 x/y 位置的组合(由于链接示例中未表示的项目的某些现实)。但我很高兴找到了答案!
最佳答案
您的示例在 Chrome 上对我来说效果很好。但实际上那只是因为 SVG 是页面上唯一的东西。如果我在 SVG 上方添加一些文本,一切都会出错。
https://jsfiddle.net/rrpfmm6d/1/
这就是你说的问题吗?
如果是这样,原因是你在使用 getBoundingClientRect()
时做出了错误的选择。 .它提供屏幕空间中的坐标。它的起点是窗口的左上角(如果是 jsfiddle,则为 iframe)。
你应该使用 getBBox()
.它返回的值与 SVG 元素位于相同的坐标空间中。它的原点(通常)位于 SVG 的左上角。
总之,使用调用getBBox()
返回的坐标在你的 <text>
元素来计算你的圈子的位置。如果圆圈插入到与文本相同的 SVG 中,则无需对 div 或 svg 偏移量进行任何调整。
关于javascript - 通过 .getBoundingClientRect() 在可变宽度的 div 中定位 SVG 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30158656/