SVG空间中foreignObject HTML元素的坐标

时间:2011-11-06 21:39:04

标签: javascript html svg

我有一个带有XHTML表的SVG文件。我想用SVG绘图(通过JavaScript)连接表的部分。例如,在以下文件中,我想将每个黄色圆圈放在红色边框右端的中心位置:

<?xml version="1.0"?>
<svg viewBox="0 0 1000 650" version="1.1" baseProfile="full"
     xmlns="http://www.w3.org/2000/svg">
  <title>Connect</title>
  <style type="text/css"><![CDATA[
    table { border-collapse:collapse; margin:0 auto; }
    table td { padding:0; border-bottom:1px solid #c00;}
    circle.dot { fill:blue }
  ]]></style>
  <foreignObject x="100" width="800" height="600" y="400"><body xmlns="http://www.w3.org/1999/xhtml"><table><thead><tr>
    <th>Space</th>
  </tr></thead><tbody>
    <tr><td><input name="name" type="text" value="One"/></td></tr>
    <tr><td><input name="name" type="text" value="Two"/></td></tr>
  </tbody></table></body></foreignObject>
  <circle class="dot" id="dot1" cx="100" cy="100" r="5" />
  <circle class="dot" id="dot2" cx="200" cy="100" r="5" />
</svg>

如何在全局SVG坐标空间中最好地找到任意HTML元素的位置?

为简单起见,请随意忽略浏览器大小调整以及可能包装<foreignObject>的任何转换堆栈。

1 个答案:

答案 0 :(得分:2)

以下是我提出的实际行动:HTML Element Location in SVG (v2)

// Find the four corners (nw/ne/sw/se) of any HTML element embedded in
// an SVG document, transformed into the coordinates of an arbitrary SVG
// element in the document.
var svgCoordsForHTMLElement = (function(svg){
  var svgNS= svg.namespaceURI, xhtmlNS = "http://www.w3.org/1999/xhtml";
  var doc  = svg.ownerDocument;
  var wrap = svg.appendChild(doc.createElementNS(svgNS,'foreignObject'));
  var body = wrap.appendChild(doc.createElementNS(xhtmlNS,'body'));
  if (typeof body.getBoundingClientRect != 'function') return;
  body.style.margin = body.style.padding = 0;
  wrap.setAttribute('x',100);
  var broken = body.getBoundingClientRect().left != 0;
  svg.removeChild(wrap);
  var pt = svg.createSVGPoint();
  return function svgCoordsForHTMLElement(htmlEl,svgEl){
    if (!svgEl) svgEl = htmlEl.ownerDocument.documentElement;
    for (var o=htmlEl;o&&o.tagName!='foreignObject';o=o.parentNode){}
    var xform = o.getTransformToElement(svgEl);
    if (broken) xform = o.getScreenCTM().inverse().multiply(xform);

    var coords = {};
    var rect = htmlEl.getBoundingClientRect();
    pt.x = rect.left; pt.y = rect.top;
    coords.nw = pt.matrixTransform(xform);
    pt.y = rect.bottom; coords.sw = pt.matrixTransform(xform);
    pt.x = rect.right;  coords.se = pt.matrixTransform(xform);
    pt.y = rect.top;    coords.ne = pt.matrixTransform(xform);

    return coords;
  };
})(document.documentElement);

以下是你如何使用它:

// Setting SVG group origin to bottom right of HTML element
var pts = svgCoordsForHTMLElement( htmlEl );
var x = pts.sw.x, y = pts.sw.y;
svgGroup.setAttribute( 'transform', 'translate('+x+','+y+')' );

注意事项:

  • 在Firefox v7中完美运行
  • 适用于Chrome v16和Safari v5,但以下情况除外:
    • 如果已调整浏览器缩放,则效果不佳。
    • 由于this Webkit bug导致<foreignObject>被旋转或歪斜,它无法正常工作。
  • 它不适用于IE9(XHTML没有显示,getTransformToElement不起作用。)