我有一个基于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>
正如您所看到的,无论定义的原点如何,Chrome都会应用从形状左上角开始的所有转换,而Firefox则会考虑定义的原点。
我是否遗漏了transform-origin
如何与SVG配合使用?
有没有人真正找到一种方法来解决这个问题而不用翻译补偿?
答案 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>