SVG transform-origin在Chrome中不起作用

cnjp1d6j  于 2023-06-19  发布在  Go
关注(0)|答案(3)|浏览(171)

我有一个基于SVG的应用程序,它大量使用了转换,如平移,旋转和缩放。虽然我在Firefox中没有问题,但在Chrome中,transform-origin属性没有考虑在内。它似乎应用了user-agent默认值0px 0px 0
下面是一个例子(JSFiddle):

<svg width="400" height="400">
  <defs>
    <rect id="shape" width="200" height="200"/>
  </defs>
  <g transform="translate(100,100)">
    <use xlink:href="#shape" style="stroke: lightgray; fill: transparent;"/>
    <ellipse cx="100" cy="100" rx="3" ry="3" style="fill: black;"/>
    <g transform="translate(0,0) scale(0.5) rotate(45)" style="transform-origin: 100px 100px;">
      <use xlink:href="#shape" style="stroke: black; fill: transparent;"/>
    </g>
  </g>
</svg>

正如你所看到的,Chrome应用从形状左上角的所有变换,而Firefox尊重定义的原点。
我是否错过了一些关于transform-origin如何与SVG一起工作的内容?
有没有人真的找到一种方法来解决这个问题,而不用翻译来补偿?

8xiog9wr

8xiog9wr1#

我回答我自己的问题是为了完全澄清SVG 1.1转换函数上的transform-origin属性是怎么回事,以及如何在Chrome 48中克服这个问题。
首先,transform-origin是一个纯CSS 3属性,它与SVG 1.1完全无关。尽管transform听起来很像transform-origin,但它们适用于不同的系统。transform存在于CSS 3和SVG 1.1中,但有单独的实现transform-origin只存在于CSS 3中,因此它不会影响SVG 1.1。transform-origin对Chrome 48中的SVG没有影响,这是意料之中的。
那么为什么transform-origin在Firefox 44中适用于SVG呢?原因还不太清楚,但似乎是Mozilla正在努力的一部分,慢慢地在Firefox中支持SVG 2。事实上,在SVG 2中,所有内容都将变成CSS 3转换(没有单独的实现),因此SVG将获得对transform-origin的支持。我在Sara Soueidan的一篇关于SVG坐标系统的优秀文章中发现了这一点。
那么,在Chrome 48中如何解决这个问题呢?它相当简单,但如果你想同时应用translate()scale()rotate(),你仍然需要计算缩放引起的偏移,并在你的翻译中补偿它。
正如Bobby Orndorff在他的回答中提到的,实际上可以通过提供额外的x和y参数来为rotate()函数提供旋转中心。这已经是一个很大的进步了。但不幸的是,scale()函数不支持这样的功能,总是从父函数的左上角开始缩放。因此,您仍然需要更正您的平移,以模拟围绕中心的比例。
以下是适用于Chrome 48和Firefox 44的最终解决方案:

<svg width="400" height="400">
  <defs>
    <rect id="shape" width="200" height="200"/>
  </defs>
  <g transform="translate(100,100)">
    <use xlink:href="#shape" style="stroke: lightgray; fill: transparent;"/>
    <ellipse cx="100" cy="100" rx="3" ry="3" style="fill: black;"/>
    <g transform="translate(50,50) scale(0.5) rotate(45, 100, 100)">
      <use xlink:href="#shape" style="stroke: black; fill: transparent;"/>
    </g>
  </g>
</svg>
izkcnapc

izkcnapc2#

这个例子是混合了CSS transform-origin和SVG变换。虽然CSS转换和SVG转换是相似的,但也有区别。例如,CSS变换可以是2D和3D,而SVG变换仅是2D。CSS transform rotate函数接受Angular 作为一个数字与一个单位的组合(例如degs,grad,rad,turn),而SVG变换接受Angular 作为数字(隐含的度单位)沿着表示旋转原点的可选的第二和第三参数(x,y)。
要让示例在Firefox和Chrome中工作,您可以使用CSS转换而不是SVG转换。比如...

<svg width="400" height="400">
  <defs>
    <rect id="shape" width="200" height="200"/>
  </defs>
  <g transform="translate(100,100)">
    <use xlink:href="#shape" style="stroke: lightgray; fill: transparent;"/>
    <ellipse cx="100" cy="100" rx="3" ry="3" style="fill: black;"/>
    <g style="transform: translate(0,0) scale(0.5) rotate(45deg); transform-origin: 100px 100px;">
      <use xlink:href="#shape" style="stroke: black; fill: transparent;"/>
    </g>
  </g>
</svg>

要让示例在Firefox、Chrome和IE中工作,您可以使用SVG transform rotate函数,并带有可选的第二个和第三个参数,而不是CSS transform-origin。比如...

<svg width="400" height="400">
  <defs>
    <rect id="shape" width="200" height="200"/>
  </defs>
  <g transform="translate(100,100)">
    <use xlink:href="#shape" style="stroke: lightgray; fill: transparent;"/>
    <ellipse cx="100" cy="100" rx="3" ry="3" style="fill: black;"/>
    <g transform="translate(0,0) scale(0.5) rotate(45,200,200)">
      <use xlink:href="#shape" style="stroke: black; fill: transparent;"/>
    </g>
  </g>
</svg>
ukqbszuj

ukqbszuj3#

神奇的词是:变压箱:填充盒;把它放在盒子里,看看奇迹发生。现在它将作为一个html对象。

相关问题