代码之家  ›  专栏  ›  技术社区  ›  Vinay Bagale

如何根据旋转/平移/缩放值计算SVG转换矩阵?

  •  40
  • Vinay Bagale  · 技术社区  · 12 年前

    我随身携带以下详细信息:

    <g transform="translate(20, 50) scale(1, 1) rotate(-30 10 25)">
    

    需要将以上行更改为:

    <g transform="matrix(?,?,?,?,?,?)">
    

    有人能帮助我实现这一点吗?

    3 回复  |  直到 7 年前
        1
  •  77
  •   Peter Collingridge    11 年前

    Translate(tx,ty)可以写成矩阵:

    1  0  tx
    0  1  ty
    0  0  1
    

    比例(sx,sy)可以写成矩阵:

    sx  0  0
    0  sy  0
    0   0  1
    

    Rotate(a)可以写成矩阵:

    cos(a)  -sin(a)  0
    sin(a)   cos(a)  0
    0        0       1
    

    旋转(a,cx,cy)是由(-cx,cy)平移、旋转一度和平移回(cx,ncy)的组合,得出:

    cos(a)  -sin(a)  -cx × cos(a) + cy × sin(a) + cx
    sin(a)   cos(a)  -cx × sin(a) - cy × cos(a) + cy
    0        0       1
    

    如果你将其与平移矩阵相乘,你会得到:

    cos(a)  -sin(a)  -cx × cos(a) + cy × sin(a) + cx + tx
    sin(a)   cos(a)  -cx × sin(a) - cy × cos(a) + cy + ty
    0        0       1
    

    它对应于SVG变换矩阵:

    (cos(a), sin(a), -sin(a), cos(a), -cx × cos(a) + cy × sin(a) + cx + tx, -cx × sin(a) - cy × cos(a) + cy + ty) .

    在您的情况下,这是: matrix(0.866, -0.5 0.5 0.866 8.84 58.35) .

    如果包含比例(sx,sy)变换,则矩阵为:

    (sx × cos(a), sy × sin(a), -sx × sin(a), sy × cos(a), (-cx × cos(a) + cy × sin(a) + cx) × sx + tx, (-cx × sin(a) - cy × cos(a) + cy) × sy + ty)

    请注意,这是假设您按照编写转换的顺序进行转换。

        2
  •  13
  •   Robert Longson    12 年前

    首先使用document.getElementById获取g元素(如果它有id属性或其他适当的方法),然后调用 consolidate 例如

    var g = document.getElementById("<whatever the id is>");
    g.transform.baseVal.consolidate();
    
        3
  •  3
  •   Eduard Kolosovskyi    7 年前

    也许有帮助:

    1. Live demo 如何找到变换点的实际坐标

    2. 公认答案的实现:

      function multiplyMatrices(matrixA, matrixB) {
          let aNumRows = matrixA.length;
          let aNumCols = matrixA[0].length;
          let bNumRows = matrixB.length;
          let bNumCols = matrixB[0].length;
          let newMatrix = new Array(aNumRows);
      
          for (let r = 0; r < aNumRows; ++r) {
              newMatrix[r] = new Array(bNumCols);
      
              for (let c = 0; c < bNumCols; ++c) {
                  newMatrix[r][c] = 0;
      
                  for (let i = 0; i < aNumCols; ++i) {
                      newMatrix[r][c] += matrixA[r][i] * matrixB[i][c];
                  }
              }
          }
      
          return newMatrix;
      }
      
      let translation = {
          x: 200,
          y: 50
      };
      let scaling = {
          x: 1.5,
          y: 1.5
      };
      let angleInDegrees = 25;
      let angleInRadians = angleInDegrees * (Math.PI / 180);
      let translationMatrix = [
          [1, 0, translation.x],
          [0, 1, translation.y],
          [0, 0, 1],
      ];
      let scalingMatrix = [
          [scaling.x, 0, 0],
          [0, scaling.y, 0],
          [0, 0, 1],
      ];
      let rotationMatrix = [
          [Math.cos(angleInRadians), -Math.sin(angleInRadians), 0],
          [Math.sin(angleInRadians), Math.cos(angleInRadians), 0],
          [0, 0, 1],
      ];
      let transformMatrix = multiplyMatrices(multiplyMatrices(translationMatrix, scalingMatrix), rotationMatrix);
      
      console.log(`matrix(${transformMatrix[0][0]}, ${transformMatrix[1][0]}, ${transformMatrix[0][1]}, ${transformMatrix[1][1]}, ${transformMatrix[0][2]}, ${transformMatrix[1][2]})`);