在 SVG 组上设置变换原点在 Firefox 中不起作用
Posted
技术标签:
【中文标题】在 SVG 组上设置变换原点在 Firefox 中不起作用【英文标题】:Setting transform-origin on SVG group not working in Firefox 【发布时间】:2013-02-14 20:29:27 【问题描述】:我在让 transform-origin 在 Firefox 中工作时遇到问题(v.18+,其他版本未测试)。 Webkit 浏览器按预期工作。我正在尝试将原点设置为组的中心,但到目前为止我尝试过的任何方法都没有奏效。
代码如下:
#test
-webkit-transform-origin: 50% 50%;
transform-origin: center center;
-webkit-animation: prop 2s infinite;
animation: prop 2s infinite;
@-webkit-keyframes prop
0%
-webkit-transform: scale(1, 1);
20%
-webkit-transform: scale(1, .8);
40%
-webkit-transform: scale(1, .6);
50%
-webkit-transform: scale(1, .4);
60%
-webkit-transform: scale(1, .2);
70%
-webkit-transform: scale(1, .4);
80%
-webkit-transform: scale(1, .6);
90%
-webkit-transform: scale(1, .8);
100%
-webkit-transform: scale(1, 1);
@keyframes prop
0%
transform: matrix(1, 0, 0, 1, 0, 0);
20%
transform: matrix(1, 0, 0, .8, 0, 0);
40%
transform: matrix(1, 0, 0, .6, 0, 0);
50%
transform: matrix(1, 0, 0, .4, 0, 0);
60%
transform: matrix(1, 0, 0, .2, 0, 0);
70%
transform: matrix(1, 0, 0, .4, 0, 0);
80%
transform: matrix(1, 0, 0, .6, 0, 0);
90%
transform: matrix(1, 0, 0, .8, 0, 0);
100%
transform: matrix(1, 0, 0, 1, 0, 0);
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16">
<g id="test">
<rect fill="#404040" x="7.062" y="3.625" />
</g>
</svg>
【问题讨论】:
FWIW,据说在 Firefox 19 beta 3 中已修复,尽管我在 Firefox 22 中仍然遇到问题。Mozilla bugzilla 列表:bugzilla.mozilla.org/show_bug.cgi?id=828286 Ugh nvm 抱歉误读,我不确定该错误是否相关... Firefox 中的 SVG 元素不支持 transform-origin。请投票bug #923193) 以获得支持。 @dotnetCarpenter 现在已在 Firefox 41+ 中修复 @zigomir 是的,你是对的!不过,它仍然不是默认的 firefox 浏览器。但是,是的,这个问题将在下一个 Firefox 版本中消失。测试:bug1013421.bmoattachments.org/attachment.cgi?id=8425610 【参考方案1】:我试图使用 CSS 过渡围绕其中心点旋转一个简单的 cog svg 图形。我在使用 Firefox 时遇到了和你一样的问题; transform-origin 似乎没有效果。
解决方案是绘制原始的svg形状,使其中心位于坐标0, 0:
<svg x="0px" y="0px" viewBox="0 0 400 400">
<rect id="myObject" x="-50" y="-50" fill="#E52420" />
</svg>
然后在其周围添加一个组并翻译到你想要的位置:
<svg x="0px" y="0px" viewBox="0 0 400 400">
<g transform="translate(150, 100)">
<rect id="myObject" x="-50" y="-50" fill="#E52420" />
</g>
</svg>
现在您可以应用应该在 Firefox 中工作的 css 转换(我使用基于用户操作 (js-rotateObject
) 的 javascript 向 html 标记添加一个类,并使用 Minimizr 检查浏览器是否可以处理转换和转换(@ 987654326@):
#myObject
transform: rotate(0deg);
transition: all 1s linear;
.csstransforms.csstransitions.js-rotateObject #myObject
transform: rotate(360deg);
希望对您有所帮助。
【讨论】:
对于那些遇到同样问题的人,这个答案很有帮助。如果您尝试在从 Firefox 55(2017 年 8 月 8 日发布)开始,现在支持“transform-box”CSS 属性。将其设置为“填充框”将在 SVG 树中的变换原点方面模仿 Chrome。
transform-origin: center; /* or transform-origin: 50% */
transform-box: fill-box;
2017 年 9 月 14 日更新
您可以在 SVG 结构中选择您需要的元素,或者,正如 Tom 在 cmets 中指出的那样,您可以简单地将其应用于 SVG 元素的所有后代(只要样式不会干扰您的任何其他元素)正在努力实现):
svg .my-transformed-element
transform-origin: center; /* or transform-origin: 50% */
transform-box: fill-box;
或
svg *
transform-origin: center; /* or transform-origin: 50% */
transform-box: fill-box;
【讨论】:
请编辑您的答案以指明应在哪些元素上设置此 CSS 道具。 (SVG?G?路径/矩形/等)它像 HTMLbox-sizing
,所以我们想要 svg * transform-box: fill-box;
吗?编辑:我最终做了后者。 svg *
已更新,感谢汤姆提供的信息! - 至于元素,它可以是 SVG 结构中需要样式的任何元素(例如制作动画) - <g>
、<circle>
、<path>
等等。
这应该是公认的答案。只是一个简单的svg * transform-box: fill-box;
为我修复了所有动画。
现在应该是答案了!
@MSC - 在做了一些测试后,我认为这可能是一个错误,但我不确定。谢谢。【参考方案3】:
@PatrickGrey 的回答对我来说非常有效,但我需要处理具有多个路径的更复杂的 SVG。我能够使用 Inkscape 完成此修复,但这是一个多步骤的过程。我建议在打开 Inkscape XML 编辑器的情况下执行此操作,这样您就可以看到正在发生的事情。
选择要变换的元素,然后选择对象>组创建一个新组。拖动该组,使其位于文档左上角的中心。这会将transform="translate(…, …)"
属性应用于组。
从菜单中选择对象>取消组合。这将“展平”变换属性,将任何坐标变换应用于组中的元素。
仍应选择原始元素。选择 Object > Group 将它们放回一个组中。如果您使用 CSS 来转换元素,请将您的 ID
或 class
属性添加到此组(XML 编辑器对此非常有用,或者您可以通过右键单击它并选择 对象属性。需要通过 XML 编辑器或稍后在文本编辑器中添加类。)。
选中组后,再次选择对象>组。这会围绕原始组创建一个新组。
将此新组拖动到文档中的正确位置。如果您使用 XML 编辑器检查 DOM,您会看到 transform="translate(…, …)"
已添加到 outer 组中。
现在可以将任何 CSS 转换应用于 inner 组,Chrome 和 Firefox 将一致地处理它们。
感谢@PatrickGrey.co.uk 的初步见解。最棘手的部分是弄清楚如何将初始变换应用于复杂对象的坐标,而无需借助头发拉扯和大量数学运算。 *** 上有几个地方记录了“分组、移动、取消分组”的技巧,但直到今天我才忘记它。希望这些步骤可以为其他人节省相当多的悲伤。
【讨论】:
这项技术对我来说非常有效。非常感谢@thirdender! 很高兴它有帮助 :-) 如果您可以帮助编辑我的答案,使其更清晰,请随意。今天重读时,我仍然觉得它非常混乱……:-p【参考方案4】:根据this bug report 中的cmets,Firefox 的transform-box
默认值与Chrome 不同。从 Firefox 55 开始,现在可以在不设置标志的情况下设置此属性。
这为我解决了这个问题:
transform-box: fill-box;
transform-origin: center center;
【讨论】:
在我的情况下,这是导致问题的原因。【参考方案5】:如果您可以使用固定的像素值,请改用它来使其工作。
-moz-transform-origin: 25px 25px;
-ms-transform-origin: 25px 25px;
-o-transform-origin: 25px 25px;
-webkit-transform-origin: 25px 25px;
transform-origin: 25px 25px;
一些浏览器仍然不支持带有百分比值的转换原点,至少不是在所有情况下。如果您没有固定的 px 值,请为每个 javascript 计算一个并使用您选择的库(如 jQuery、Greensock 等)来设置该值。
【讨论】:
【参考方案6】:FWIW,我能够使用 Greensock 解决我的问题,使用 TweenMax 为内部的各个路径设置动画,这在 Firefox Gecko 和 Webkit 浏览器(Safari/Chrome)中工作得更好(不完全是确定如何,但它对我有用)
有一个带有两个齿轮的 SVG,我想在另一个形状内旋转。所以我给每个齿轮一个唯一的 id (id="gear1", id="gear2") 然后用 Greensock 旋转它们,如下所示:
TweenMax.to("#gear1", 3.2,
repeat: -1, //repeat infintely
ease: Linear.easeNone, //no easing, linear motion
rotation:360, //amount to rotate (full)
transformOrigin:"center" //transform origin that WORKS :)
);
#gear2 相同,时间稍有不同,并且在浏览器中运行良好。
【讨论】:
【参考方案7】:您的 css 代码中缺少 -moz-transform-origin
。
#test
-webkit-transform-origin: 50% 50%;
-moz-transform-origin: 50% 50%;
...
【讨论】:
【参考方案8】:另外,您可以考虑为不支持transform-box: fill-box
的 Firefox 版本禁用动画
像这样:
@supports (-moz-transform: rotate(0deg)) and (not (transform-box: fill-box))
#test
animation: none;
第一个语句只是检查您是否在使用 firefox,因为无论如何您都不想在其他浏览器上禁用它。第二条语句检查浏览器是否支持transform-box
-property。我在当前项目中使用了它,它就像一个魅力。
【讨论】:
以上是关于在 SVG 组上设置变换原点在 Firefox 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章