Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotating a Svg path around center using matrix

I have many svg shape of different sizes, I have to rotate them with different angle dynamically.I want to rotate them centrally using matrix, I am facing a problem in calculating e,f of matrix. How the calculate e,f in matrix(a,b,c,d,e,f). I have an angle, but does not know to calculate new position, so it looks it rotated centrally.Here is an example shape which I have rotated at 45 degree, enter image description here

     <rect x="0" y="0" width="50" height="50" style="stroke: #3333cc;fill:none;" transform="matrix(1,0,0,1,100,100)"></rect>

   <rect x="0" y="0" width="50" height="50" style="fill: #3333cc" transform="matrix(0.707,-0.707,0.707,0.707,100,100)"></rect>
like image 729
Atta Ch Avatar asked Jul 16 '15 06:07

Atta Ch


People also ask

How do I rotate a path in SVG?

Just use the element type selector and add the transform: rotate(180deg) property to it like in the below snippet.

How to rotate svg line?

Rotate. The rotate(<a> [<x> <y>]) transform function specifies a rotation by a degrees about a given point. If optional parameters x and y are not supplied, the rotation is about the origin of the current user coordinate system. If optional parameters x and y are supplied, the rotation is about the point (x, y) .

How do I rotate a SVG file 90 degrees?

To rotate an SVG, upload your vector file or drag n drop it to the editor. Next, click on the SVG file to activate the four-pointers. Hold the top pointer to rotate the SVG clockwise or anticlockwise until you're satisfied with the orientation and position.


1 Answers

An intro to how transforms and matrix multiplication works is beyond the scope of a Stack Overflow answer. There are plenty of online resources for that.

And you can read about how SVG transforms work in the SVG specification:

http://www.w3.org/TR/SVG/coords.html

But basically to rotate by angle (a) around a specific point (cx,cy), you have to combine (with matrix multiplication) the three operations:

  1. translate the centre back to the origin (-cx, -cy)
  2. perform the rotation (a)
  3. translate back to the original position
[1 0 cx] [cos(a) -sin(a) 0] [1 0 -cx]
[0 1 cy] [sin(a)  cos(a) 0] [0 1 -cy]
[0 0 1 ] [  0       0    1] [0 0  1 ]

When you multiply those three matrices together you get a matrix of the form:

[cos(a) -sin(a) (-cos(a) * x + sin(a) * y + x)]
[sin(a)  cos(a) (-sin(a) * x - cos(a) * y + y)]
[0         0               1          ]

or in SVG form:

matrix( ca, sa, -sa, ca, (-ca * x + sa * y + x), (-sa * x - ca * y + y) )

Where:

ca = cos(angle)
sa = sin(angle)

Here is a demo. The green rectangle is using transform="rotate(a,x,y)" and the red rectangle is using our calculated equivalent.

var matrix = getMatrixForRotation(45, 250, 250);

document.getElementById("myrect").setAttribute("transform", matrix);



function getMatrixForRotation(a, cx, cy)
{
  var ca = Math.cos(a * Math.PI / 180);
  var sa = Math.sin(a * Math.PI / 180);

  var a = ca.toFixed(4);
  var b = sa.toFixed(4);
  var c = (-sa).toFixed(4);
  var d = ca.toFixed(4);
  var e = (-ca * cx + sa * cy + cx).toFixed(4);
  var f = (-sa * cx - ca * cy + cy).toFixed(4);

  return "matrix(" + [a,b,c,d,e,f].join(' ') + ")";
}
<svg width="500" height="500">
  
  <rect x="100" y="150" width="300" height="200" fill="#eee"/>
  
  <rect x="100" y="150" width="300" height="200" fill="none"
        stroke="green" stroke-width="10"
        transform="rotate(45 250 250)"/>
  
  <rect x="100" y="150" width="300" height="200" fill="none"
        stroke="red" stroke-width="4"
        id="myrect"/>
  
</svg>
like image 191
Paul LeBeau Avatar answered Sep 19 '22 00:09

Paul LeBeau