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,
<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>
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,
<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>
Share
Improve this question
edited Jul 17, 2015 at 6:14
Atta Ch
asked Jul 16, 2015 at 6:20
Atta ChAtta Ch
3094 silver badges9 bronze badges
5
-
1
Is there a reason you are using
matrix()
and notrotate(angle, cx,cy)
? – Paul LeBeau Commented Jul 16, 2015 at 10:22 -
The trick is to draw the
<rect>
centered around Origin(0,0)
, then userotate(degree)
andtranslate(x,y)
. Works all the time and easier to read vsmatrix(....)
– Alvin K. Commented Jul 16, 2015 at 18:12 - 1 @PaulLeBeau I want to learn the mechanism, how the rotation works in matrix – Atta Ch Commented Jul 17, 2015 at 7:33
- @AlvinK. I still I need to solve it using matrix – Atta Ch Commented Jul 17, 2015 at 7:39
-
rotate(degree offset-x offset-y)
whereoffset-x
= width/2 &offset-y
= height/2. Check the docsmatrix(...)
is the equivalent of bothrotate()
andtranslate()
. In another words, doesn't matter if you use one or the other, amounts to the same rotation. – Alvin K. Commented Jul 17, 2015 at 16:43
2 Answers
Reset to default 10An 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/TR/SVG/coords.html
But basically to rotate by angle (a) around a specific point (cx,cy), you have to bine (with matrix multiplication) the three operations:
- translate the centre back to the origin (-cx, -cy)
- perform the rotation (a)
- 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>
Basically what you need to do is plus your X position and negative your 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 rect is the normal straight one which is not rotated. To rotate this in the center of the first rect 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 simply use those values in your second rect so the new X position would be 25 and the new Y position would be -25