为什么我无法围绕 SVG 中的给定点旋转路径

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

让我们考虑一下 this SVG file from Openclipart (link to raw SVG file)。作为参考,它看起来像这样:

我现在想旋转指针,以便让时钟显示任意时间。

我确定时针是由这个 path 元素编码的:

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

我还确定双手交叉的中心圆是由这个ellipse元素编码的:

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

因为这个 ellipse 元素有属性 cx="150.233"cy="151.011" 我推断这个椭圆的中心位于点 (150.233, 151.011) 并且,以合理的准确性,我可以假设此时双手交叉,这就是我应该旋转双手的确切点。

所以对于初学者来说,让我们尝试将小时时钟旋转 10°。 Having read the MDN documentation of the transform attribute 我认为这可以通过将属性 transform="rotate(10 150.233 151.011)" 添加到上述 path 元素来完成,获得以下代码:

<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)" />

不幸的是,结果证明我的假设是错误的:

我有什么不明白的,如何旋转这只手?

SVG 使用坐标的 "userspace" 概念。如果一个元素有一个 transform 属性,它的属性中表示的坐标指的是局部坐标系,即 userspace,它是从其父元素的坐标系转换而来的,就像 [=12] =]属性描述。因此它也不同于根 <svg> 元素的坐标系。

当元素的父元素具有转换属性时,也会发生同样的情况:用户空间坐标系源自父元素,不同于根元素。 (使用元素 "establishing a viewport" 会变得更加复杂,但让我们跳过这里。)

您没有注意到的是,您为中心标识的椭圆有一个父 <g> 元素,其属性为 transform="scale(2.4444516,2.4444516)" 如果将 cx 和 cy 值与这些缩放因子相乘,您得到

cx = 367.23729
cy = 369.13908

这非常适合整个 SVG 的大小。它具有属性 width="734.47461" height="738.27081",如果将它们减半,则与椭圆的值差别不大。

检查手元素或其父元素的坐标系未变换后,您现在可以将旋转设置为

transform="rotate(10 367.23729 369.13908)"

如果您继续使用 SVG,阅读规范中的 chapter about coordinate systems and transformations 肯定是个好主意。