SVG转换 - 起源不适用于Chrome

时间:2016-02-23 17:31:27

标签: google-chrome svg

我有一个基于SVG的应用程序,它大量使用转换,如翻译,旋转和缩放。虽然我在Firefox中没有问题,但在Chrome中,transform-origin属性不会被考虑在内。它似乎应用了用户代理默认值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>

transform-origin issue

正如您所看到的,无论定义的原点如何,Chrome都会应用从形状左上角开始的所有转换,而Firefox则会考虑定义的原点。

我是否遗漏了transform-origin如何与SVG配合使用?

有没有人真正找到一种方法来解决这个问题而不用翻译补偿?

2 个答案:

答案 0 :(得分:10)

我正在回答我自己的问题,以便完全澄清SVG 1.1转换函数的transform-origin属性以及如何在Chrome 48中克服此问题。

首先,transform-origin是纯CSS 3属性,它与SVG 1.1完全无关。尽管transform听起来很像transform-origin,但它们适用于不同的系统。 {3}和SVG 1.1中都存在transform,但单独实现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 coordinate systems的优秀文章中发现了这一点。

现在如何在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>

答案 1 :(得分:2)

该示例是混合CSS变换原点和SVG变换。虽然CSS变换和SVG变换相似,但存在差异。例如,CSS变换可以是2D和3D,而SVG变换仅是2D。 CSS变换旋转函数接受角度作为与单位组合的数字(例如,凹陷,渐变,弧度,转弯),而SVG变换接受角度作为数字(具有隐含的度数单位)以及可选的第二和第三参数(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变换旋转功能,使用可选的第二个和第三个参数而不是CSS变换原点。例如......

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