Javascript SVG中矩阵的理解

Javascript SVG中矩阵的理解,javascript,matrix,svg,Javascript,Matrix,Svg,我需要帮助深入理解SVG中的矩阵。我已经知道矩阵,我想旋转和缩放而不使用缩放或旋转词。我想使用transform='matrix(a,b,c,d,e,f')。我知道“a/d”值决定刻度,“e/f”决定位置。tan(b),tan(c)确定倾斜。cos(a),sin(b),-sin(c),cos(d)确定角度。但我想知道这是如何工作的,我需要在理解SVG中的矩阵时得到彻底的帮助。矩阵操作由单个“局部”变换(即平移、旋转、缩放、倾斜)通过矩阵串联(即乘法)组成 例如,如果要围绕点旋转对象(x,y),则

我需要帮助深入理解SVG中的矩阵。我已经知道矩阵,我想旋转和缩放而不使用缩放或旋转词。我想使用transform='matrix(a,b,c,d,e,f')。我知道“a/d”值决定刻度,“e/f”决定位置。tan(b),tan(c)确定倾斜。cos(a),sin(b),-sin(c),cos(d)确定角度。但我想知道这是如何工作的,我需要在理解SVG中的矩阵时得到彻底的帮助。

矩阵操作由单个“局部”变换(即平移、旋转、缩放、倾斜)通过矩阵串联(即乘法)组成

例如,如果要围绕点旋转对象
(x,y)
,则应转换为
(x,y)
,旋转
r
度,然后转换回原始位置
(-x,-y)

通过通常被称为“链接”(如上所述)的方式,将每个连续的“局部”转换组合起来以产生结果。因此,在转换链的任何位置,“本地”转换空间(在该位置)由之前的所有操作组成

这意味着,当转换SVG元素的某些参数(即translate)时,转换将应用于其当前的转换空间。因此,例如,如果元素已旋转30度,则
(8,5)
的平移不会向右移动8度,向下移动5度,而是相对于当前位置旋转(8,5)30度

所以这有点难对付

有助于解决这一复杂问题的一种方法是将变换矩阵分解为各自的总变换(即总平移、总旋转/倾斜、总尺度),但分解并没有说明组合总变换中的各个基本变换,也没有说明它们发生的顺序。这是一个问题,因为二维变换是不可交换的,例如
translate(x,y)->rotate(r)
rotate(r)->translate(x,y)
不同

我发现的最好的方法是只按特定顺序组合转换,并按该顺序跟踪总计,然后在引入新转换时,使用已跟踪的总计,更新正在修改的转换并重新组合整个转换

像这样:(伪代码)

要清楚的是,这并不是说矩阵不是表示变换的好方法,也不是说矩阵不是表示变换的更好方法——远远不是

变换矩阵是一个强大的工具,如果使用得当,它们在处理复杂动画时非常有效,但在所有情况下都可以使用

这可能有点高级,但是有关使用矩阵变换的动画的更多信息,这个简短的代码示例提供了大量的信息和参考

更新: 请注意上面链接中提出的分解倾斜因子

仅计算单个倾斜因子(x中),因为x和y中的倾斜相当于x和组合(偏移)旋转中的倾斜

组合x倾斜和y倾斜(包括或不包括旋转或平移,如我以上首选的构图顺序)将导致不同的x倾斜、旋转(例如,如果最初没有构图,则非零旋转)、平移(例如,相对于分解旋转的一定量的偏移,以代替原始y偏移),但没有可恢复的y偏移-使用链接分解方法

这是组合仿射矩阵的一个限制。因此,生成最终结果矩阵通常应视为单向计算

// EDIT: initialize components (new SVGMatrix returns the identity matrix)
var transX=0, transY=0, rot=0, scaX=0, scaY=0, skwX=0, skwY=0, matrix = new SVGmatrix();

// example rotate
function rotate(svgEl, angle){
    rot = rot + angle;
    updateTransform();
    applyTransform(svgEl);
};

function updateTransform(){
    // the order that I've found most convenient
    // (others may do it differently)
    matrix.translate(transX, transY);
    matrix.rotate(rot);
    matrix.scale(scaX, scaY);
    matrix.skewX(skwX);
    matrix.skewY(skwY);
};

function applyTransform(el){
    el.transform = matrix;
};