Inkscape 中的 SVG 变换原点损坏

SVG transform-origin broken in Inkscape

我有这个 SVG 文件: xml

<svg xmlns="http://www.w3.org/2000/svg" width="300mm" height="300mm" id="image">
  <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

  <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865" transform="rotate(51)"
    transform-origin="113.38582677299999 113.38582677299999"></rect>

  <path d="
        M 170.0787401595,113.38582677299999
        Q 109.97448081636158,111.75869821811467 149.06383319514674,157.4444954545483
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  <g transform="rotate(1.6451612903225807)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(47.70967741935484)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.9291728801154,111.85730708558926 151.53378395847778,155.32411227472434
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(3.2903225806451615)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(44.41935483870968)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.88671463478482,111.95717607594642 153.8779628220461,153.06546067295844
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(4.935483870967742)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(41.12903225806451)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.84714108325986,112.0582228564553 156.08864114581934,150.6759873101943
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(6.580645161290323)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(37.83870967741935)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.81048485026771,112.16036412340621 158.158530434343,148.16357016015428
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(8.225806451612904)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(34.54838709677419)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.7767761554767,112.26351567078673 160.08080636654395,145.5364925360554
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(9.870967741935484)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(31.258064516129032)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.74604278858297,112.36759245970185 161.84913129517457,142.80341578094155
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(11.516129032258066)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(27.96774193548387)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.71831008640042,112.47250868848064 163.45767514171737,139.97335071167026
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(13.161290322580646)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(24.677419354838708)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.6936009119729,112.57817786341175 164.90113461786132,137.05562791070196
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(14.806451612903226)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(21.387096774193548)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.67193563572567,112.68451287004946 166.1747507101772,134.0598669636379
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(16.451612903225808)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(18.096774193548384)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.65333211867201,112.79142604503151 167.27432437034577,130.99594474392939
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(18.096774193548388)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(14.806451612903224)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.6378056976883,112.89882924834941 168.19623035920955,127.87396284932184
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(19.741935483870968)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(11.516129032258064)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.6253691728703,113.0066339360117 168.9374291990041,124.70421429739422
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(21.387096774193548)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(8.225806451612904)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.61603279698062,113.11475123304022 169.49547719436387,121.49714958999664
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(23.03225806451613)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(4.935483870967737)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.60980426699628,113.22309200673944 169.86853448906282,118.26334225847053
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>

  <g transform="rotate(24.67741935483871)" transform-origin="30mm 30mm">

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"></rect>

    <rect x="170.0787401595" y="112.81889763913499" width="555.5905511877" height="0.566929133865"
      transform="rotate(1.6451612903225765)" transform-origin="113.38582677299999 113.38582677299999"></rect>

    <path d="
        M 170.0787401595,113.38582677299999
        Q 109.60668871776325,113.33156694017794 170.05537113192838,115.01345400324652
      " fill="none" stroke-width="0.566929133865" stroke="#000000"></path>

  </g>
</svg>

这是它在 Chrome 和 Firefox 中的呈现方式(以及我希望它的外观):

(截图是手工裁剪的,这不是实际渲染大小)

下面是它在 GIMP、Inkscape、Blender、Gwenview 和可能许多其他应用程序中的呈现方式:

使用一些几何我发现浏览器将 transform-origin 解释为相对于文档边缘的坐标(如我所料),而在 GIMP 和其他人中,旋转轴位于左上角,而不管 transform-origin.

此 SVG 由脚本生成。我可以重写它以避免使用转换,但我想知道是否有更简单的方法让 transform-origin 工作。

您正在使用 CSS Transforms Level 1 Candidate Recommendation, and you are using them as presentation attributes. transform-origin as a presentation attribute was only introduced in the 2017 working draft. While browser vendors have the capacity to bring up their products to new spec standards even before they reach recommendation status, most open source projects have not. For Inkscape, you have to live with the implementation according to the SVG 1.1 attribute 标准中定义的 transformtransform-origin,这与 CSS 不兼容。

但这对你的情况来说并不是真正的问题。您只能将 transform-originrotate() 函数结合使用。为此,SVG 属性语法和 CSS 属性 函数符号之间有一个有用的区别:您可以在函数内定义旋转中心。 (此语法 存在于 rotate(),但不适用于 scale()skewX()skewY()。)

一个CSS规则(注意强制单位)

style="transform:rotate(51deg);transform-origin:113.38582677299999px 113.38582677299999px;"

可以写成SVG属性

transform="rotate(51 113.38582677299999 113.38582677299999)"

但要注意

第二个条件意味着您不能使用 mm 个单位,但需要将它们重新计算为 px 个单位。