Javascript 如何获取空SVG组的位置?

Javascript 如何获取空SVG组的位置?,javascript,d3.js,svg,Javascript,D3.js,Svg,我在d3工作,我在定位和空组方面有困难 我有一个svg: 我想动态地将一条线添加到b类的组中,我想添加它,这样线的第一个点的坐标将与a组中线的第二个点的坐标一致 因为SVG对象的坐标是相对于它们的容器的,所以要获得相对坐标,我首先使用getBoundingClientRect获得g.a内的线的绝对位置和g.b的绝对位置 问题是g.b的坐标,如果它是空的,就完全乱了。我必须创建一个伪对象才能正确获取它们: d3.selectmysvg.b.appendcircle.attrr,0.attrfill

我在d3工作,我在定位和空组方面有困难

我有一个svg:

我想动态地将一条线添加到b类的组中,我想添加它,这样线的第一个点的坐标将与a组中线的第二个点的坐标一致

因为SVG对象的坐标是相对于它们的容器的,所以要获得相对坐标,我首先使用getBoundingClientRect获得g.a内的线的绝对位置和g.b的绝对位置

问题是g.b的坐标,如果它是空的,就完全乱了。我必须创建一个伪对象才能正确获取它们:

d3.selectmysvg.b.appendcircle.attrr,0.attrfill,透明 .attracx,0.attracy,0;
此外,如果我创建半径大于零的圆,其b组的位置将发生移动。

您可以使用基本DOM接口在两个坐标系之间进行转换。接口定义了

在应用“transform”属性(如果有)后,将当前元素上的用户坐标系中的变换矩阵返回到参数元素上的用户坐标系(如果有)

值得注意的是,Chrome48+已经放弃了对此的支持。但是,有一种相当薄的polyfill可供选择:

// Polyfill needed for Chrome 48+
SVGElement.prototype.getTransformToElement = 
    SVGElement.prototype.getTransformToElement || function(elem) {
        return elem.getScreenCTM().inverse().multiply(this.getScreenCTM());
    };
因为它只是这一行,所以在代码中直接使用它可能更容易

然后,您可以使用帮助器获取从组a中的元素到组b中的元素所需的转换矩阵:

看看这个工作示例,它在b组中画了一条红线,从a组中的线的末端开始,到坐标100100:

//铬>48需要Polyfill SVGElement.prototype.getTransformToElement=SVGElement.prototype.getTransformToElement | | functionelem{ 返回elem.getScreenCTM.inverse.multiplythis.getScreenCTM; }; var groupB=document.querySelectorg.b; var line=document.querySelector.a行; //创建辅助点 var point=document.getElementByIdmysvg.createSVGPoint; point.x=line.getAttributex2; 点.y=line.getAttributey2; //根据坐标系之间的转换计算新线的起点。 point=point.MatrixTransferorMLine.GetTransferorMToElementGroupB; //D3应用于简化一些事情。 //新线从a组中的线末端绘制到100100。 d3.selectgroupB.appendline 艾特先生{ x1:x点, y1:点y, x2:100, y2:100 }; 线{ 笔画:黑色; } b线{ 笔画:红色; }
空对象实际上没有位置,因为它们会自动调整其内容的大小。如果你把东西放进去,元素的位置应该会改变,这就是元素的工作原理。getBBox在之前帮助我获得svg元素的位置。也许你不知道,这就是为什么我要提到它。看起来Firefox没有getScreenCTM。我正在使用Firefox 41.0.2。我想它应该在那里。它在较低版本中似乎有很多错误,但我认为它并没有消失。@MarcoSulla FF实际上有getTransferorMToElement方法,甚至不应该运行polyfill的代码。您是按原样使用polyfill还是提取了一层衬里?在执行后一种操作时,请记住将其替换为要转换到的元素,因为在这种情况下,这很可能会引用另一个对象,而该对象可能确实没有实现该方法。@MarcoSulla Firefox确实有GetScreenCMyes抱歉,getScreenCTM是受支持的,并且代码可以工作,但就我所见,我总是需要一个辅助点。这个解决方案更快吗?
// Create a helper point
var point = document.getElementById("mysvg").createSVGPoint();
point.x = line.getAttribute("x2");
point.y = line.getAttribute("y2");

// Calculate starting point of new line based on transformation between coordinate systems.
point = point.matrixTransform(line.getTransformToElement(groupB));