问题
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