Rotate the Svg path around the center using the matrix

I have many svg shapes of different sizes, I have to rotate them from different angles dynamically. I want to rotate them centrally using a matrix, I am faced with the problem of computing the e, f matrix. How to calculate e, f in a matrix (a, b, c, d, e, f). I have a corner, but I don’t know to calculate the new position, so it looks like it is rotated centrally. Here is an example of a shape that I rotated 45 degrees, 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> 
+5
source share
2 answers

An introduction to how transformations and matrix multiplication work is beyond the scope of the answer. There are many online resources for this.

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 an angle (a) around a certain point (cx, cy), you need to combine (with matrix multiplication) three operations:

  • move the center back to the origin (-cx, -cy)
  • turn (a)
  • move back to the starting 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 these three matrices together, you get a shape matrix:

  [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 the form of SVG:

 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 uses transform="rotate(a,x,y)" , and the red rectangle uses our computed 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> 
+2
source

Basically what you need to do is plus your X position and negative Y position. For example

If you have this code

  <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="25" y="-25" width="50" height="50" style="fill: #3333cc" transform="matrix(0.5,0.5,-0.5,0.5,100,100)"></rect> </svg> 

The first line is a normal line that does not rotate. To rotate this in the center of the first rectangle, you need to first

 Divide the width by your x transform (0.5) : 50 / 0.5 = 25 Divide the height by your y transform (0.5) : 50 / 0.5 = 25 

Then just use these values ​​in the second rectangle so that the new X position is 25 and the new Y position is -25

0
source

All Articles