admin管理员组

文章数量:1178526

I have the the following Transform Matrix in CSS

// rotate the element 60deg
element.style.transform = "matrix(0.5,0.866025,-0.866025,0.5,0,0)"

And i can find the rotation using this...

// where a = [0.710138,0.502055,-0.57735,1,0,0]
var rotation = ((180/Math.PI) * Math.atan2( ((0*a[2])+(1*a[3])),((0*a[0])-(1*a[1]))) - 90
console.log(rotation); // ~60

Similarly for skew if...

// skew(30deg,-50deg) 
element.style.transform = "matrix(1,-1.19175,0.57735,1,0,0)"

var skewY = ((180/Math.PI) * Math.atan2( ((0*a[2])+(1*a[3])),((0*a[0])-(1*a[1]))) - 90;
var skewX = (180/Math.PI) * Math.atan2( ((1*a[2])+(0*a[3])),((1*a[0])-(0*a[1])));

console.log([skewX,skewY]); // ~= [30,-50] 

However as soon as i use both skew and rotation everything goes weird not least because the formula for rotation is identical to that of skew... so the formulas can't be right.

How do i determine both rotation & skew where both attributes have been applied and all i know is the Matrix Transform.

Also scale messed up my skew values, which i dont think it should.

I have the the following Transform Matrix in CSS

// rotate the element 60deg
element.style.transform = "matrix(0.5,0.866025,-0.866025,0.5,0,0)"

And i can find the rotation using this...

// where a = [0.710138,0.502055,-0.57735,1,0,0]
var rotation = ((180/Math.PI) * Math.atan2( ((0*a[2])+(1*a[3])),((0*a[0])-(1*a[1]))) - 90
console.log(rotation); // ~60

Similarly for skew if...

// skew(30deg,-50deg) 
element.style.transform = "matrix(1,-1.19175,0.57735,1,0,0)"

var skewY = ((180/Math.PI) * Math.atan2( ((0*a[2])+(1*a[3])),((0*a[0])-(1*a[1]))) - 90;
var skewX = (180/Math.PI) * Math.atan2( ((1*a[2])+(0*a[3])),((1*a[0])-(0*a[1])));

console.log([skewX,skewY]); // ~= [30,-50] 

However as soon as i use both skew and rotation everything goes weird not least because the formula for rotation is identical to that of skew... so the formulas can't be right.

How do i determine both rotation & skew where both attributes have been applied and all i know is the Matrix Transform.

Also scale messed up my skew values, which i dont think it should.

Share Improve this question edited Nov 12, 2015 at 12:53 AndreaBogazzi 14.7k3 gold badges41 silver badges67 bronze badges asked Feb 24, 2011 at 16:02 DrewDrew 1,4402 gold badges11 silver badges14 bronze badges 3
  • interesting question. you have six elements in each matrix. Is this a 3x3 matrix with the last row implicitly set to (0,0,1)? – vidstige Commented Feb 24, 2011 at 17:16
  • yes, transform Matrices used in javascript ( 2dcanvas relataed ) have latest row implicitly set to [0,0,1] – AndreaBogazzi Commented Aug 20, 2015 at 8:10
  • i polished the answer a little bit more, it works very good – AndreaBogazzi Commented Nov 29, 2015 at 11:18
Add a comment  | 

2 Answers 2

Reset to default 27

I needed same functionality and today I ended up with this code that works very good.

I took inspiration from here: https://www.youtube.com/watch?v=51MRHjKSbtk and from the answer below, without the hint QR decomposition i would never find it out

I worked on a 2x2 case, i will try to expand to 2x3 to include also translations. But it should be easy

var a = [a, b, c, d, e, f];
var qrDecompone = function(a) {
  var angle = Math.atan2(a[1], a[0]),
      denom = Math.pow(a[0], 2) + Math.pow(a[1], 2),
      scaleX = Math.sqrt(denom),
      scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX,
      skewX = Math.atan2(a[0] * a[2] + a[1] * a[3], denom);
  return {
    angle: angle / (Math.PI / 180),  // this is rotation angle in degrees
    scaleX: scaleX,                  // scaleX factor  
    scaleY: scaleY,                  // scaleY factor
    skewX: skewX / (Math.PI / 180),  // skewX angle degrees
    skewY: 0,                        // skewY angle degrees
    translateX: a[4],                // translation point  x
    translateY: a[5]                 // translation point  y
  };
};

It looks like that the last two items in the transformMatrix, before decomposition, are translation values. You can extract them directly.

Found the definition of your matrices here. We have the transformation matrix T

    / a b tx \
T = | c d ty |
    \ 0 0 1  /

For the following expression

element.style.transform = "matrix(a,b,c,d,tx,ty)"

In order to retrive the parameters used to build up this matrix we need to first find a decomposition of the matrix T. Assuming the skew is applied after the rotation we can find the QR-decomposition:

QR = T

The rotation will be found inside the Q matrix in the form of a pure rotation matrix. You can then use trigonometry to find out the single rotation angle, for example like so

rotation = atan2(Q21, Q11)

The skew and translation will be found in the R matrix.

    / sx   k  tx \
R = |  0  sy  ty |
    \  0   0   1 /

Where sx and sy is the scale and k represents the shear. I dont know how this shear relates to the css-skew.

I don't know if the QR decomposition is availble in javascript, but it should be easy enough to implement using the Numerical Recipes as reference.

Not a complete answer to get the parameters to create a new matrix object, but should set you off in the right direction!

本文标签: javascriptFind the Rotation and Skew of a Matrix transformationStack Overflow