简体   繁体   English

在 SVG 组上设置转换原点在 Firefox 中不起作用

[英]Setting transform-origin on SVG group not working in Firefox

I am having an issue with getting transform-origin to work in Firefox (v.18+, other versions not tested).我在让 transform-origin 在 Firefox 中工作时遇到问题(v.18+,其他版本未测试)。 Webkit browsers work as expected. Webkit 浏览器按预期工作。 I'm trying to set the origin to the center of the group, but nothing I've tried has worked so far.我试图将原点设置为组的中心,但到目前为止我尝试过的一切都没有奏效。

Here's the code:这是代码:

 #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" width="128px" height="128px" viewBox="0 0 16 16"> <g id="test"> <rect fill="#404040" x="7.062" y="3.625" width="1.875" height="8.75"/> </g> </svg>

I was attempting to rotate a simple cog svg graphic around its centre point using a CSS transition.我试图使用 CSS 过渡围绕其中心点旋转一个简单的 cog svg 图形。 I had the same problem as you with Firefox;我在 Firefox 上遇到了和你一样的问题; transform-origin seemed to have no effect.变换原点似乎没有效果。

The solution was to draw the original svg shape so that its centre was at coordinate 0, 0:解决方案是绘制原始 svg 形状,使其中心位于坐标 0, 0:

<svg x="0px" y="0px" width="400px" height="400px" viewBox="0 0 400 400">
    <rect id="myObject" x="-50" y="-50" fill="#E52420" width="100" height="100"/>
</svg>

Then add a group around it and translate to the position you want:然后在它周围添加一个组并转换到您想要的位置:

<svg x="0px" y="0px" width="400px" height="400px" viewBox="0 0 400 400">
    <g transform="translate(150, 100)">
        <rect id="myObject" x="-50" y="-50" fill="#E52420" width="100" height="100"/>
    </g>
</svg>

Now you can apply css transitions that should work in Firefox (I add a class to the HTML tag using JavaScript based on a user action ( js-rotateObject ) and use Minimizr to check that the browser can handle transforms and transitions ( .csstransforms.csstransitions ):现在您可以应用应该在 Firefox 中工作的 css 转换(我使用基于用户操作( js-rotateObject )的 JavaScript 向 HTML 标签添加一个类,并使用 Minimizr 检查浏览器是否可以处理转换和转换( .csstransforms.csstransitions ):

#myObject{
    transform: rotate(0deg);
    transition: all 1s linear;
}

.csstransforms.csstransitions.js-rotateObject #myObject{
    transform: rotate(360deg);
}

Hope that helps.希望有帮助。

As of Firefox 55 (released August 8, 2017), the "transform-box" CSS property is now supported.从 Firefox 55(2017 年 8 月 8 日发布)开始,现在支持“transform-b​​ox”CSS 属性。 Setting it to "fill-box" will mimic that of Chrome with respect to transform-origin in SVG trees.将其设置为“fill-box”将在 SVG 树中的转换原点方面模仿 Chrome。

transform-origin: center; /* or transform-origin: 50% */
transform-box: fill-box;

Update 2017-9-14更新 2017-9-14

You can select the elements that you need within the SVG structure or, as Tom points out in the comments, you can simply apply it to all decendants of the SVG element (as long as the styling does not interfere with anything else you are attempting to achieve):您可以在 SVG 结构中选择您需要的元素,或者,正如 Tom 在评论中指出的那样,您可以简单地将其应用于 SVG 元素的所有后代(只要样式不干扰您尝试的任何其他内容)达到):

svg .my-transformed-element {
    transform-origin: center; /* or transform-origin: 50% */
    transform-box: fill-box;
}

or要么

svg * {
    transform-origin: center; /* or transform-origin: 50% */
    transform-box: fill-box;
}

@PatrickGrey's answer worked perfectly for me, but I needed to handle a much more complex SVG with several paths. @PatrickGrey 的回答对我来说非常有效,但我需要处理具有多个路径的更复杂的 SVG。 I was able to accomplish this fix using Inkscape, but it was a multi-step process.我能够使用 Inkscape 完成此修复,但这是一个多步骤的过程。 I recommend doing this with the Inkscape XML Editor open so you can watch what's happening.我建议在打开 Inkscape XML 编辑器的情况下执行此操作,以便您可以观察发生的情况。

  1. Select the elements you want to transform and choose Object > Group to make a new group.选择要变换的元素,然后选择“对象”>“组”以创建一个新组。 Drag this group so that it is centered over the top left corner of the document.拖动该组使其位于文档左上角的中心。 This applies a transform="translate(…, …)" attribute to the group.这将transform="translate(…, …)"属性应用于组。

  2. Choose Object > Ungroup from the menu.从菜单中选择对象 > 取消组合 This will "flatten" the transform attribute, applying any coordinate transformations to the elements in the group.这将“展平”变换属性,将任何坐标变换应用于组中的元素。

  3. The original elements should still be selected.仍应选择原始元素。 Choose Object > Group to put them back into a group.选择对象 > 组将它们放回组中。 If you are using CSS to transform the elements, add your ID or class attribute to this group (The XML editor comes in handy for this bit, or you can modify the group's ID by right-clicking it and choosing Object Properties . Classes will need to be added through the XML editor or later in your text editor.).如果您使用 CSS 来转换元素,请将您的IDclass属性添加到该组(XML 编辑器在这一点上派上用场,或者您可以通过右键单击它并选择Object Properties来修改组的 ID。类将需要将通过 XML 编辑器添加或稍后在您的文本编辑器中添加。)。

  4. With the group selected, choose Object > Group again.选择组后,再次选择对象 > 组 This creates a new group around the original group.这将在原始组周围创建一个新组。

  5. Drag this new group to the correct location in the document.将此新组拖到文档中的正确位置。 If you inspect the DOM using the XML editor, you'll see the transform="translate(…, …)" is added to the outer group.如果您使用 XML 编辑器检查 DOM,您将看到transform="translate(…, …)"添加到外部组。

  6. Any CSS transforms can now be applied to the inner group, and they will be handled consistently by Chrome and Firefox.现在可以将任何 CSS 转换应用于内部组,并且它们将由 Chrome 和 Firefox 统一处理。

Thanks to @PatrickGrey.co.uk for the initial insight.感谢@PatrickGrey.co.uk 的初步见解。 The trickiest part was figuring out how to apply the initial transform to the complex object's coordinates without resorting to hair pulling and extensive maths.最棘手的部分是弄清楚如何将初始变换应用于复杂对象的坐标,而无需借助头发和大量数学运算。 The "Group, move, Ungroup" trick was documented a few places on StackOverflow, but I'd forgotten it until today. StackOverflow 上的一些地方记录了“分组、移动、取消分组”技巧,但直到今天我才忘记它。 Hopefully these steps can save someone else a fair amount of grief.希望这些步骤可以为其他人节省相当多的悲伤。

According to the comments in this bug report , Firefox's default value for transform-box is different than Chrome's.根据此错误报告中的评论,Firefox 的transform-box的默认值与 Chrome 的不同。 As of Firefox 55, this property can now be set without setting a flag.从 Firefox 55 开始,现在可以在不设置标志的情况下设置此属性。

This fixed the issue for me:这为我解决了问题:

transform-box: fill-box;
transform-origin: center center;

If you can use a fixed pixel value, use that instead to make it work.如果您可以使用固定像素值,请改用它来使其工作。

-moz-transform-origin: 25px 25px;
-ms-transform-origin:  25px 25px;
-o-transform-origin: 25px 25px;
-webkit-transform-origin:  25px 25px;
transform-origin: 25px 25px;

Some browsers still don't support transform-origin with percentage values the way they should – at least not in all situations.一些浏览器仍然不支持使用百分比值的转换原点,至少不是在所有情况下。 If you don't have a fixed px value calculate one per javascript and use the library of your choice (like jQuery,Greensock,etc) to set the value.如果您没有固定的 px 值,请为每个 javascript 计算一个并使用您选择的库(如 jQuery、Greensock 等)来设置该值。

FWIW, I was able to solve my problem with Greensock, using TweenMax to animate individual paths inside, and this worked in Firefox Gecko, and Webkit browsers (Safari/Chrome) It does a better job of calculating the origin (not exactly sure how, but it worked for me) FWIW,我能够使用 Greensock 解决我的问题,使用 TweenMax 为内部的单个路径设置动画,这在 Firefox Gecko 和 Webkit 浏览器(Safari/Chrome)中工作,它在计算原点方面做得更好(不完全确定如何,但它对我有用)

Had an SVG with two gears I wanted to rotate inside another shape.有一个带有两个齿轮的 SVG,我想在另一个形状内旋转。 So I gave each gear a unique id (id="gear1", id="gear2") and then rotated them with Greensock, something like this:所以我给每个齿轮一个唯一的 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 :) 
});

Same for #gear2 with slightly different timing, and works great across browsers.与#gear2 相同,但时间略有不同,并且在浏览器中效果很好。

Is missing the -moz-transform-origin from your css code.缺少 css 代码中的-moz-transform-origin

#test{
    -webkit-transform-origin: 50% 50%;
    -moz-transform-origin: 50% 50%;
    ...
}

As an addition, you might consider disabling the animation for Firefox versions which don't support transform-box: fill-box另外,您可以考虑禁用不支持transform-box: fill-box Firefox 版本的动画

Like this:像这样:

@supports (-moz-transform: rotate(0deg)) and (not (transform-box: fill-box)) {
    #test {
        animation: none;
    }
}

The first statement is just to check if you're on firefox, since you don't want to disable it on other browsers anyway.第一条语句只是检查您是否在使用 Firefox,因为无论如何您都不想在其他浏览器上禁用它。 The second statement checks if the transform-box -property is supported by the browser.第二个语句检查浏览器是否支持transform-box属性。 I used this in a current project and it works like a charm.我在当前的项目中使用了它,它就像一个魅力。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM