为什么transformorigin不适用于使用内联SVG的Firefox,还有其他选择吗



我发现Firefox与Chrome、Edge和Opera相比不一致。当使用CSS类时,每个浏览器都能很好地处理transform-origin。但是,当我将transform-origin作为属性放置在SVG元素上时,FF会忽略这种效果。下面的演示代码。我的主要问题是如何绕过这一点,但我也很好奇这是否是预期行为。

CSStransform-origin适用于FF.

<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 1000'>	
	<style>	
		.centered{			
			transform-origin: center;
		}
	</style>
	<path fill='#500' d='M500 500 400 400 400 600 600 600 600 400z' transform='scale(2)' class='centered'/>
</svg>

内联SVG似乎无法识别transform-origin(在Chrome/edge中始终有效)

<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 1000'>	
	<path fill='#500' d='M500 500 400 400 400 600 600 600 600 400z' transform='scale(2)' transform-origin='center'/>
</svg>


Edit:另一位用户指出,这个问题类似于如何在SVG中设置转换原点,但他们的前提非常宽泛(如何),要么是错误的,要么是过时的(发布于8.5年前)。

"我尝试使用变换原点属性,但它不影响任何东西">

也许浏览器支持有所改善,但我的问题特别表明,transform-origin在所有现代浏览器中都可以完美地作为CSS规则,或者在除FireFox之外的所有现代浏览器中将其作为表示属性。这种差异可能导致一个解决方案是该线程独有的,而第二个解决方案则是对其他线程的新处理。

更不用说,他们的问题集中在JavaScript实现上,并且是在FireFox无法识别"中心"或无单位数字等关键字的时候发布的,这有损于核心SVG标记问题,即FireFox解释的表示属性transform-origin=''与其他浏览器不同。

总的来说,标记为正确的答案在所有情况下都有效。然而,我正在编写另一个解决方案,因为它是最容易实现的。但请注意,它只适用于transform,不适用于patternTransform。虽然非FireFox浏览器可以识别这两个属性的transform-origin,但我的解决方案不适用于FireFox上的patternTransform

在样式属性(style='transform-origin:center')中添加transform-origin而不是其自己的表示属性(transform-origin='center')适用于transform,如下所示。这甚至适用于数据URI中的SVG。

<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 1000'>    
<path fill='#500' d='M500 500 400 400 400 600 600 600 600 400z' transform='scale(2)' style='transform-origin:center'/>
</svg>

我已经解决了这个问题,但我(到目前为止)无法向您全面解释它为什么有效。

要知道的第一件重要事情是,您可以链接SVG转换

因此,无论在哪里编写transform="scale(2)",都可以向链中添加translate(x, y),如下所示:

transform="scale(2) translate(x, y)"

到目前为止,一切都很好。。。但如果scale2,那么我们应该给translatexy什么值?

为了找到答案,我决定叠加更大的和子组合更小比例的SVG形状(彩虹的每种颜色一个),看看我能找到什么图案。

灰色形状的顶部,我放置了一个大小相同的绿色的形状。

我将绿色形状转换为:

transform="scale(1) translate(0, 0)"

这样它将与您原来的灰色形状完全一致。

然后,我开始子组合较大比例的版本(黄色橙色红色),并叠加较小比例的版本。

我预测xy在每种情况下都与应用于该形状的scale因子有关,也与原始viewBox的总体大小有关。

有了3个较小的版本和3个较大的版本,模式出现了:

  • 红色8x&y变换值为50% of ((1000 / 8) - 1000)
  • 橙色4倍大/x&y变换值为50% of ((1000 / 4) - 1000)
  • 黄色2倍大/x&y变换值为50% of ((1000 / 2) - 1000)
  • 绿色1倍大/x&y变换值为50% of ((1000 / 1) - 1000)
  • 蓝色0.5倍大/x&y变换值为50% of ((1000 / 0.5) - 1000)
  • Indigo0.25倍大/x&y变换值为50% of ((1000 / 0.25) - 1000)
  • 0.125倍大/x&y变换值为50% of ((1000 / 0.125) - 1000)

由此,我们可以得出结论,如果您将一个形状定位在viewBox50%, 50%中心,并且您希望将该形状显示在与scale(2)相同的位置,则您还必须为的x应用translate

50% of ((width of canvas / scale-factor) - (width of canvas))

其中50%对应于要使形状居中的x位置。

和一个用于的ytranslate

50% of ((height of canvas / scale-factor) - (height of canvas))

其中50%对应于要使形状居中的y位置。

这种方法一直有效,但我还没有花足够的时间仔细观察,以正确理解原因。

工作示例:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
<!-- Grey Original -->
<path fill="#555" d="M500 500 400 400 400 600 600 600 600 400z" />
<!-- Red Transform [50% of ((1000 / 8) - 1000) is -437.5] -->
<path fill="rgb(255, 0, 0)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(8) translate(-437.5, -437.5)" />
<!-- Orange Transform [50% of ((1000 / 4) - 1000) is -375] -->
<path fill="rgb(255, 125, 0)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(4) translate(-375, -375)" />
<!-- Yellow Transform [50% of ((1000 / 2) - 1000) is -250] -->
<path fill="rgb(255, 255, 0)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(2) translate(-250, -250)" />
<!-- Green Transform [50% of ((1000 / 1) - 1000) is 0] -->
<path fill="rgb(0, 125, 0)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(1) translate(0, 0)" />
<!-- Blue Transform [50% of ((1000 / 0.5) - 1000) is 500] -->
<path fill="rgb(0, 0, 125)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(0.5) translate(500, 500)" />
<!-- Indigo Transform [50% of ((1000 / 0.25) - 1000) is 1500] -->
<path fill="rgb(63, 0, 255)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(0.25) translate(1500, 1500)" />
<!-- Violet Transform [50% of ((1000 / 0.125) - 1000) is 3500] -->
<path fill="rgb(199, 125, 243)" d="M500 500 400 400 400 600 600 600 600 400z" transform="scale(0.125) translate(3500, 3500)" />
</svg>

最新更新