Pregunta

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.

¿Fue útil?

Solución

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.

Otros consejos

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!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top