SVG矩阵分解

7

在 SVG 中,我们有一个方法叫做 element.getCTM(),它返回一个 SVGMatrix,如下所示:

[a c e][b d f][0 0 1] 

我希望从这个矩阵中计算出sx、sy和旋转角度。

帮我解决这个问题。 - rsk
1个回答

11

这个主题有很多要学习和阅读的内容。我会给出一个基本答案,但请注意,如果你想做游戏或动画,这不是正确的方法。

a == sxd == sy,所以你可以像这样访问它们:

var r, ctm, sx, sy, rotation;

r   = document.querySelector('rect'); // access the first rect element
ctm = r.getCTM();
sx  = ctm.a;
sy  = ctm.d;

现在来讲旋转部分,a == cos(angle)b == sin(angle)。asin和acos不能单独给出完整的角度,但它们可以一起使用。你需要使用atan,因为 tan = sin/cos,而对于这种问题,你实际上需要使用atan2
RAD2DEG = 180 / Math.PI;
rotation = Math.atan2( ctm.b, ctm.a ) * RAD2DEG;

如果您学习反三角函数单位圆, 您就会明白为什么这样做是有效的。
这里是W3C关于SVG变换的不可或缺的资源: http://www.w3.org/TR/SVG/coords.html。往下滚动一点,您可以阅读更多关于我上面提到的内容。
更新,编程示例用于如何以编程方式执行动画。将变换单独存储,并在更新时覆盖/更新SVG元素变换。
var SVG, domElement, ...

// setup
SVG        = document.querySelector( 'svg' );
domElement = SVG.querySelector( 'rect' );
transform  = SVG.createSVGTransform();
matrix     = SVG.createSVGMatrix();
position   = SVG.createSVGPoint();
rotation   = 0;
scale      = 1;

// do every update, continuous use
matrix.a = scale;
matrix.d = scale;
matrix.e = position.x;
matrix.f = position.y;

transform.setMatrix( matrix.rotate( rotation ) );
domElement.transform.baseVal.initialize( transform ); // clear then put

如何查找SVG动画的分解值? - rsk
你想做什么动画?你需要哪些数值?请描述得更详细一些。 - bennedich
我想说的是,如果我有一个SVG动画,其中许多动画节点(如animateTransform(translate,scale,rotate)和animateMotion)附加到容器节点上。因此,如果我想将此动画简化为单个平移、旋转、缩放和扭曲,可能可以借助CTM来实现,因为CTM是组合变换矩阵。问题是,我应该将哪些值放入平移、旋转、缩放和扭曲节点中,以达到当前的变换效果。 - rsk
那需要很多工作。当你使用animateTransformanimateMotion和其他动画元素时,你不应该以编程的方式控制它们。如果你想以编程的方式控制动画,你需要直接使用元素变换。我在上面更新了我的答案,并提供了一个例子。 - bennedich
我已经找到了使用SVD的解决方案,它给出了像A = USV这样的矩阵,其中U和V是旋转矩阵,而S是比例矩阵。假设U的第一行是[a11 a12],第二行是[a21 a22]。如何获取坐标系轴旋转的角度? - rsk

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