获取SVG元素的当前矩阵变换

12

我知道一种非常简单的方法来获取任何SVG元素的当前矩阵变换:

// 't' is a string
var t = window.getComputedStyle(nativeElement, null).transform
console.log(t);

问题在于先前的方法返回的数字最多只有六位小数。例如,先前的代码可能会返回:
matrix(0.965926, 0.258819, -0.258819, 0.965926, 0, 0)

有没有一种更准确地获取任何SVG元素的矩阵变换的方法?

转换是属性还是样式? - Robert Longson
transform是一个属性:https://developer.mozilla.org/zh-CN/docs/Web/SVG/Attribute/transform - Cequiel
你把它当作问题中的样式来处理,这就是我问的原因。如果它是一个样式,那么就没有太多可以做的了,如果它是一个属性,你可以通过DOM获取它。 - Robert Longson
这是一个准确的二维变换矩阵 - 二维仿射矩阵中只有六个数字(a-f)。您所说的更准确是什么意思? - user1693593
“transform”属性返回六个浮点数,精度有限(6位小数)。所谓“准确”,是指返回更多的小数位。该问题已在下一个答案中得到解决。 - Cequiel
3个回答

15

要将当前的transform属性作为SVGMatrix对象获取,您可以使用:

element.transform.baseVal.consolidate().matrix

var myrect = document.getElementById("myrect");

console.log(myrect.transform.baseVal.consolidate().matrix);
<svg>
  <rect id="myrect" width="10" height="10" transform="scale(2) rotate(45)"/>
</svg>


你认为我下面回答中的解决方案怎么样?它是相同的矩阵对象,还是你知道一些与你的解决方案不同的地方? - Bharata
1
正如Robert在下面所说,你的解决方案是不同的。只有当没有祖先元素具有变换时,它才会给出相同的结果。这包括其他导致转换的属性,例如viewBox - Paul LeBeau

2
如果您知道您的SVG元素没有被转换的祖先,那么您可以使用SVGelement.getCTM()函数,因为它更短。我认为函数名称中的CTM是“current transformation matrix”的缩写。

var rect = document.querySelector("#rect");

console.log(rect.getCTM());
<svg>
    <rect id="rect" width="10" height="10" transform="scale(2) rotate(45)"/>
</svg>

区别:rect.getCTM()与rect.transform.baseVal.consolidate().matrix
但是你应该小心使用这个函数,因为它只在没有祖先元素有变换的情况下才会给出与矩阵rect.transform.baseVal.consolidate().matrix相同的结果。例如:

var rect = document.querySelector("#rect"),
    ctmMatrix = rect.getCTM(),
    baseValMatrix = rect.transform.baseVal.consolidate().matrix;

console.log('CTM Matrix: translateX = '+ctmMatrix.e+', translateY = '+ctmMatrix.f);
console.log('BaseVal Matrix: translateX = '+baseValMatrix.e+', translateY = '+baseValMatrix.f);
<svg>
    <g transform="translate(35,45)">
        <rect id="rect" width="10" height="10" transform="translate(35,45)"/>
    </g>
</svg>

我感谢@PaulLeBeau解释这些矩阵之间的区别。

1
这是元素及其祖先的变换。 - Robert Longson

2

整合可以改变您的元素“transform”属性值。您还可以通过将元素矩阵转换为父级而获得矩阵,而无需更改转换属性。

请参阅有关以下内容的文档:

getTransformToElement

function getMatrix(element) {
  var matrix = element.parentNode
     .getScreenCTM()
     .inverse()
     .multiply(element.getScreenCTM());
  return matrix;
}
var myrect = document.getElementById("myrect");

console.log(getMatrix(myrect));
<svg>
  <rect id="myrect" width="10" height="10" transform="scale(2) rotate(45)"/>
</svg>


请查看此帖子:https://dev59.com/6VbUa4cB1Zd3GeqPCtwo此外,您可能希望将参考元素作为函数的参数而不是硬编码到 element.parentNode,像这样:const getMatrix = (to, from) => to.getScreenCTM().inverse().multiply(from.getScreenCTM());. - V. Rubinetti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接