通过.getBoundingClientRect()在可变宽度div

时间:2015-05-11 02:03:18

标签: javascript svg d3.js

我有点烦人的问题。

我试图根据现有的一组具有相似属性的SVG文本元素来定位一堆SVG圈元素。

圆形元素是在一个与文本元素完全不同的过程中创建的,因此使用与旧元素相同的变换等定位新元素并不是一个可行的选择。

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

使用.getBoundingClientRect(),我可以获得新元素的正确大小/排列,但由于包含svg的div的宽度是可变的,因此总是有点奇怪的偏移,我可以& #39; t完全考虑到了。

我创建了一个简单的问题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位置的组合(由于项目的某些现实未在链接示例中表示)。但我很高兴能找到答案!

1 个答案:

答案 0 :(得分:4)

您的示例在Chrome上适用于我。但实际上,这只是因为SVG是页面上唯一的东西。如果我在SVG上面添加一些文字,那么一切都会出错。

https://jsfiddle.net/rrpfmm6d/1/

这是你在说的问题吗?

如果是这样,原因是因为您在使用getBoundingClientRect()时做出了错误的选择。它在屏幕空间中提供坐标。它的原点是窗口的左上角(或者是jsfiddle的iframe)。

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

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