通过.getBoundingClientRect()在可变宽度div中定位SVG元素



我有一个令人讨厌的问题。

我正在尝试根据现有的共享类似属性的SVG文本元素来定位一堆SVG圆元素。

圆元素是在非常独立的过程中而不是文本元素创建的,因此仅使用相同的变换等定位新元素。因为旧的元素不是可行的选项。

我试图使用.getBoundingClientRect()来获取位置,因为文本元素被转换为位置(so.getBbox()不是选项),而不是由x和y属性定位。

使用.getBoundingClientRect(),我可以获得新元素的正确大小/布置,但是由于含SVG的Div的宽度是可变的,因此总会有一些怪异的偏移for。

我在这里创建了一个简化的我的问题示例。调整并刷新页面以查看行动中的问题。

我用来定位圆元素的代码在下面复制。

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的情况下)。

您应该使用getBBox()。它返回的值与SVG元素相同的坐标空间。它的起源是(通常)在SVG的左上方。

总而言之,使用通过在<text>元素上调用getBBox()返回的坐标来计算圆的位置。如果将圆圈插入与文本相同的SVG中,则无需使用DIV或SVG偏移进行任何调整。

最新更新