Why am I failing to rotate a path around a given point in SVG

橙三吉。 提交于 2021-01-28 07:41:23

问题


Let's consider this SVG file from Openclipart (link to raw SVG file). For reference, it looks like this:

I now want to rotate the hands so that I can make the clock show some arbitrary time.

I have determined that the hour hand is encoded by this path element:

<path
   d="m 458.13588,295.06406 c 1.74675,-16.11195 25.92429,-46.33386 37.207,-59.62773 l -0.0945,-0.0895 c -12.66188,11.97753 -41.49863,37.74816 -57.33149,40.35684 -30.58445,5.03466 -23.84883,26.09555 -19.57494,34.86553 l -52.97792,55.87976 6.16814,5.91214 53.02794,-55.93477 c 9.10302,3.92158 30.23513,9.51278 33.57547,-21.36261 z"
   id="path526"
   inkscape:connector-curvature="0"
   style="fill:url(#linearGradient4636);display:inline"
   inkscape:transform-center-y="-65.845483"
   sodipodi:nodetypes="cccccccccc"
   inkscape:transform-center-x="-63.497113" />

I have also determined that the central circle where both hands cross is encoded by this ellipse element:

<ellipse
     cx="150.233"
     cy="151.011"
     rx="8.0819998"
     ry="8.125"
     id="ellipse542"
     sodipodi:cx="150.233"
     sodipodi:cy="151.011"
     sodipodi:rx="8.0819998"
     sodipodi:ry="8.125"
     style="fill:url(#radialGradient4393)"
     d="m 158.315,151.011 c 0,4.48732 -3.61843,8.125 -8.082,8.125 -4.46356,0 -8.082,-3.63768 -8.082,-8.125 0,-4.48731 3.61844,-8.125 8.082,-8.125 4.46357,0 8.082,3.63769 8.082,8.125 z" />

Since this ellipse element has attributes cx="150.233" and cy="151.011" I reason that this ellipse's center is located at point (150.233, 151.011) and, with a reasonable accuracy, I can assume that both hands cross at this point and this is the exact point I should rotate the hands about.

So for starters let's try rotating the hour clock by, let's say, 10°. Having read the MDN documentation of the transform attribute I reason this can be done by adding the attribute transform="rotate(10 150.233 151.011)" to the aforementioned path element, obtaining the following code:

<path
   d="m 458.13588,295.06406 c 1.74675,-16.11195 25.92429,-46.33386 37.207,-59.62773 l -0.0945,-0.0895 c -12.66188,11.97753 -41.49863,37.74816 -57.33149,40.35684 -30.58445,5.03466 -23.84883,26.09555 -19.57494,34.86553 l -52.97792,55.87976 6.16814,5.91214 53.02794,-55.93477 c 9.10302,3.92158 30.23513,9.51278 33.57547,-21.36261 z"
   id="path526"
   inkscape:connector-curvature="0"
   style="fill:url(#linearGradient4636);display:inline"
   inkscape:transform-center-y="-65.845483"
   sodipodi:nodetypes="cccccccccc"
   inkscape:transform-center-x="-63.497113"
   transform="rotate(10 150.233 151.011)" />

Unfortunately, the results prove my assumption wrong:

What am I failing to understand and how to rotate this hand?


回答1:


SVG works with the notion of a "userspace" for coordinates. If an element has a transform attribute, the coordinates expressed in its attributes refer to a local coordinate system, the userspace, that is transformed from that of its parent element, just as the transform attribute describes. Consequently it also differs from the coordinate system of the root <svg> element.

The same happens when a parent of an element has a transform attribute: the userpace coordinate system derives from the parent and differs from that of the root. (It gets more complicated with elements "establishing a viewport", but lets skip this here.)

What you failed to notice is that the ellipse you identified for the center has a parent <g> element with an attribute transform="scale(2.4444516,2.4444516)" If you multiply the cx and cy values with these scaling factors, you get

cx = 367.23729
cy = 369.13908

That is a pretty good fit with the size of the SVG as a whole. It has attributes width="734.47461" height="738.27081", which, if you halve them, differ only insignificantly from the values for the ellipse.

Having checked that the coordinate systems of the hands elements or their parents are not transformed, you can now set the rotation as

transform="rotate(10 367.23729 369.13908)"

If you continue to work with SVGs, reading the chapter about coordinate systems and transformations in the spec is certainly a good idea.



来源:https://stackoverflow.com/questions/49592963/why-am-i-failing-to-rotate-a-path-around-a-given-point-in-svg

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!