【问题标题】:How to calculate SVG transform matrix from rotate/translate/scale values?如何从旋转/平移/缩放值计算 SVG 变换矩阵?
【发布时间】:2013-02-14 13:14:51
【问题描述】:

我有以下详细信息:

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

需要将上面的行改为:

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

谁能帮我实现这个目标?

【问题讨论】:

    标签: svg coordinate-transformation


    【解决方案1】:

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

    var g = document.getElementById("<whatever the id is>");
    g.transform.baseVal.consolidate();
    

    【讨论】:

    • 我正在尝试使用 Objective C/iOS 来实现这一点。有没有什么通用的方法来获取矩阵?
    • 虽然彼得斯的回答解释了理论,以及你如何手动计算矩阵,但我认为罗伯茨的回答应该是公认的。 el.transform.baseVal.consolidate() 是您应该使用的。无需重新发明轮子。
    • @Manfred OP 无法使用它,正如他对我的回答的评论中所解释的那样,他到底为什么会接受它?
    • 老实说,我没有阅读他的评论,但 OP 没有在问题中提到 Objective C/iOS。我遇到了与 OPs 问题中所述相同的问题,并且几乎接受了接受的答案,尽管本机 javascript 函数 consolidate() 是我真正需要的。
    • @Manfred 他们是休息时间 ;-),提问者在写问题时通常没有明确设置他们操作的约束条件。很高兴我的回答对你有所帮助。
    【解决方案2】:

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

    1  0  tx
    0  1  ty
    0  0  1
    

    Scale(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
    

    Rotate(a, cx, cy) 是 (-cx, cy) 的平移、a 度的旋转和返回 (cx, cy) 的平移的组合,得到:

    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)

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

    【讨论】:

    • 你能详细说明 a、cx、cy、tx 和 ty 吗?这样我就可以试一试了。
    • 在您的示例中,a=-30(度),cx=10,cy=25,tx=20,ty=50(sx=1,sy=1)。通常,旋转以 rotate(a, cx, cy) 形式给出,平移以 translate(tx, ty) 形式给出。
    • 抱歉,'Rotate(a, cx, cy)' 中的点在 '-cx.cos(a)' 中代表什么?来自 JavaScript 背景,我不明白在没有 Math.cos() 的情况下直接将 cos/sin 应用于对象意味着什么。
    • @NickBudden 我将它用作乘法的简写,但我已切换到乘法符号以减少歧义。
    • 这非常有用。我已经很多年没有做过矩阵计算了。所以 cx 和 cy 是偏移量,不是坐标...?
    【解决方案3】:

    也许有帮助:

    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]})`);
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-09
      • 1970-01-01
      • 1970-01-01
      • 2013-01-17
      • 2012-03-05
      • 2016-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多