7

In svg we have method element.getCTM() which returns a SVGMatrix as:

[a c e][b d f][0 0 1] 

I want to calculate sx , sy and angle of rotation from this matrix.

Mahmoud Gamal
  • 78,257
  • 17
  • 139
  • 164
rsk
  • 81
  • 1
  • 6

1 Answers1

11

There is a lot to read and learn on this subject. I'll give a basic answer, but be aware, if you are trying to do a game or animations this is NOT the way to do it.

a == sx and d == sy, so you'll access these like this:

var r, ctm, sx, sy, rotation;

r   = document.querySelector('rect'); // access the first rect element
ctm = r.getCTM();
sx  = ctm.a;
sy  = ctm.d;

Now for the rotation a == cos(angle) and b == sin(angle). Asin and acos can't alone give you the complete angle, but together they can. You want to use atan since tan = sin/cos and for just this kind of problem you actually want to use atan2:

RAD2DEG = 180 / Math.PI;
rotation = Math.atan2( ctm.b, ctm.a ) * RAD2DEG;

If you study the inverse trigonometric functions and the unit circle you'll understand why this works.

Here is W3C's indespensible resource on SVG transformations: http://www.w3.org/TR/SVG/coords.html. Scroll down a bit and you can read a lot more about what I've mentioned above.

UPDATE, example usage how to programmatically do animations. Keep the transformations stored separately and when these are updated, overwrite/update the SVG element transform.

var SVG, domElement, ...

// setup
SVG        = document.querySelector( 'svg' );
domElement = SVG.querySelector( 'rect' );
transform  = SVG.createSVGTransform();
matrix     = SVG.createSVGMatrix();
position   = SVG.createSVGPoint();
rotation   = 0;
scale      = 1;

// do every update, continuous use
matrix.a = scale;
matrix.d = scale;
matrix.e = position.x;
matrix.f = position.y;

transform.setMatrix( matrix.rotate( rotation ) );
domElement.transform.baseVal.initialize( transform ); // clear then put
bennedich
  • 12,150
  • 6
  • 33
  • 41
  • How to find decomposed values for svg animation ? – rsk Jan 21 '12 at 10:38
  • What animations do you want to do? What values do you need? Please describe more. – bennedich Jan 21 '12 at 12:42
  • I want to say that if I've a svg animation where many animation nodes like animateTransform(translate, scale, rotate) and animateMotion are appended to a container node. So if I want to simplify this animation into single translate , rotate , scale and skew which may be possible with the help of ctm because ctm is combined transformation matrix.Do the ques is what values should I put into translate, rotate , scale and skew nodes to get to the current transformation. – rsk Jan 23 '12 at 09:49
  • That requires ALOT of work. When you use `animateTransform`, `animateMotion` and other animation elements you are not supposed to control them programmatically. If you want to control animations programmatically you want to work directly with the elements transforms. I updated my answer above with an example. – bennedich Jan 23 '12 at 23:57
  • I've found out the solution using SVD which gives me matrices like A = USV* where U and V* are the rotation matices and S is scale matrix.Suppose 1st row of U is [a11 a12] and 2nd row is [a21 a22] . How do I get angle about which coordinate system axes is rotated? – rsk Jan 30 '12 at 13:22