如何获得svgElement的规模?

时间:2016-02-22 03:58:37

标签: javascript html5 svg

我正在研究svg。

<div id="wrap"  style="transform: scale(2); width:300;height:300;">
  <svg id="real" style="border:red 10px solid;" >
    <rect/>
  </svg>
</div>
var e = document.getElementById("real");
//an api to get scale from e directly ??

我的问题是,如何获得这个svgElement的规模?

我尝试了e.getCTM()e.getScreen()。矩阵不包含比例信息。

请给我一些建议。

2 个答案:

答案 0 :(得分:2)

Another SO answer显示了如何使用element.getBoundingClientRect().width / element.offsetWidth获取元素相对于文档的比例。但是,svg元素没有offsetWidth属性。因此,一种解决方案是临时预置一个&#34; offsetWidth-able&#34;元素到svg元素,例如a div,读取此临时助手的比率,然后将其删除。如果插入的元素通过CSS应用了意外的缩放变换(如代码片段所示),则插入的元素应该直接应用transform: scale(1);样式。

更新:当包含比例的CSS转换直接应用于svg元素本身时,会出现进一步的复杂情况。在这种情况下,需要解析样式,可以使用getComputedStylegetPropertyValue来完成,并从返回的矩阵字符串中提取缩放值。然后需要乘以前置div的相对比例。

进一步更新:此解决方案目前似乎无法在Safari中使用,因为尽管我可以找到的文档表明它应该是,但浏览器仍无法识别insertAdjacentHTML。 (这是Safari错误还是我错过了什么?)但是,该解决方案在Firefox和Chrome中都有效。

&#13;
&#13;
var e = document.getElementById("real");
var computedTransform = window.getComputedStyle(e).getPropertyValue("transform");
if (computedTransform === "none") {
  eDirScale = 1;
} else {
  var matrix = computedTransform.match(/matrix\(([^\)]*)\)/)[1].split(/, *| +/);
  var scaleX = Math.sqrt(matrix[0] * matrix[0] + matrix[1] * matrix[1]);
  var scaleY = Math.sqrt(matrix[2] * matrix[2] + matrix[3] * matrix[3]);
  if (scaleX !== scaleY) throw "non-uniform scaling";
  eDirScale = scaleX;
}
var eRelScale = e.getBoundingClientRect().width / e.offsetWidth;
e.insertAdjacentHTML('beforebegin', '<div id="temporaryPrepended" style="transform: scale(1)"></div>');
var prepended = document.getElementById("temporaryPrepended");
var pRelScale = prepended.getBoundingClientRect().width / prepended.offsetWidth;
prepended.parentNode.removeChild(prepended);
var scale = pRelScale * eDirScale;

document.write("<p>scale directly on 'svg': " + eDirScale + "</p>");
document.write("<p>scale on 'svg' relative to document: " + eRelScale + ", i.e. doesn't work in e.g. Firefox and, while it might work in Chrome (in Feb 2016), apparently won't in the near future</p>");
document.write("<p>scale on prepended 'div' relative to document: " + pRelScale + "</p>");
document.write("<p>total scale on 'svg' relative to document: " + scale + "</p>");
&#13;
div {
  transform: scale(4);
}
&#13;
<div id="wrap"  style="transform: scale(2); width:300;height:300;">
  <svg id="real" style="transform: translate(10px, 10px) scale(1.5); border:red 10px solid; opacity: 0.3;" >
    <rect/>
  </svg>
</div>
&#13;
&#13;
&#13;

当您运行上面的代码段时,您可能需要在代码段窗口中向下滚动或点击&#34;完整页面&#34;看结果。

答案 1 :(得分:0)

这是不可能的,或者更好地将`real element 不是进行转换。如果 继承转换,它将有效地缩放两次

寻找getComputedStyle,但它会告诉你同样的事情。作为参考,此处包含 继承的属性:

&#13;
&#13;
var e = document.getElementById("real");
console.log(window.getComputedStyle(e)["transform"]);
console.log(window.getComputedStyle(e)["color"]);
&#13;
<div id="wrap"  style="transform: scale(2); color: blue; width:300; height:300;">
<svg id="real" style="border: red 10px solid;" >
     <rect/>
</svg>
</div>
&#13;
&#13;
&#13;