为什么我无法围绕 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 肯定是个好主意。
让我们考虑一下 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 肯定是个好主意。