最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Rotating a Svg path around center using matrix - Stack Overflow

programmeradmin0浏览0评论

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 not rotate(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 use rotate(degree) and translate(x,y). Works all the time and easier to read vs matrix(....) – 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) where offset-x = width/2 & offset-y = height/2. Check the docs matrix(...) is the equivalent of both rotate() and translate(). 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
Add a ment  | 

2 Answers 2

Reset to default 10

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/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:

  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>

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

发布评论

评论列表(0)

  1. 暂无评论