首页 > 解决方案 > 与 Blink 和 Gecko 相比,为什么 Webkit/Safari(iOS、macOS)以不同的顺序呈现我的 SVG 转换?

问题描述

我有一个星号图标的最小 SVG 图像:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
    <defs>
        <style>
        .a {
            fill: red;
            transform-box: fill-box;
            transform-origin: center;
        }
        </style>
    </defs>
    <!-- x = 45 because it's 10px wide and centered around x=50, so x0 == 45, x1 == 55 -->
    <rect class="a" x="45" y="0" width="10" height="100"/>
    <rect class="a" x="45" y="0" width="10" height="100" transform="rotate(-45)"/>
    <rect class="a" x="45" y="0" width="10" height="100" transform="rotate( 45)"/>
    <rect class="a" x="45" y="0" width="10" height="100" transform="rotate(-90)"/>
</svg>

这在 Firefox 75 和 Chrome 80 中正确呈现,但在 iOS 或 macOS 上的 Safari 中不正确:

火狐 75:

在此处输入图像描述

铬 80:

在此处输入图像描述

iOS 13 上的 Safari

但在 Safari 上,与每个元素上的属性transform-origin相比,似乎被忽略或乱序应用:transform=""<rect>

在此处输入图像描述

有人告诉我它会在 macOS Safari 上呈现相同的损坏图像(我现在无法立即访问 macOS Safari,所以我无法从那里发布屏幕截图,抱歉)。

我在 Google 上搜索了 Safari/WebKit 是否缺乏对 的支持transform-boxtransform-origin或者transform="rotate(deg)"据我所知,Safari 多年来都完全支持它们——所以我不明白为什么它会应用这些转换——无序并导致渲染损坏。

标签: svgsafariwebkitchromium

解决方案


在 Safari 中摆弄 SVG 后,Safari 的 Web Inspector似乎确实识别了transform-originSVG 样式属性,但在应用转换时它实际上并没有使用它,这很奇怪(例如使用transform-origin: center;transform-origin: 0px 0px没有transform-origin: 50px 50px效果) - 所以修复在于使用其他方式更改旋转中心。

据我所知,macOS Safari 和 iOS Safari 都只transform-origin用于使用属性的基于 CSS 的转换,transform不是在使用基于属性的 SVG 转换时使用transform=""- 而 Blink 和 Gecko 都transform-origin用于基于属性和基于 CSS 的转换.

使用translate步骤

一种方法是添加一个translate步骤,使旋转中心在画布中居中,然后执行旋转,然后撤消该translate步骤:

transform="translate( 50, 50 ) rotate(45) translate( -50, -50 )"

像这样:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
    <rect fill="red"    x="45" y="0" width="10" height="100" />
    <rect fill="blue"   x="45" y="0" width="10" height="100" transform="translate(50,50) rotate(-45) translate(-50,-50)" />
    <rect fill="green"  x="45" y="0" width="10" height="100" transform="translate(50,50) rotate( 45) translate(-50,-50)" />
    <rect fill="orange" x="45" y="0" width="10" height="100" transform="translate(50,50) rotate(-90) translate(-50,-50)" />
</svg>

更好的方法:使用rotate( angle, x, y )

我没有对链应用初始translate步骤,而是看到转换函数支持使用附加参数指定旋转中心 - 所以这适用于 Safari、Chrome (+Edge +Opera) 和 Firefox:transformrotate

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
    <rect fill="red"    x="45" y="0" width="10" height="100" />
    <rect fill="blue"   x="45" y="0" width="10" height="100" transform="rotate(-45, 50, 50)" />
    <rect fill="green"  x="45" y="0" width="10" height="100" transform="rotate( 45, 50, 50)" />
    <rect fill="orange" x="45" y="0" width="10" height="100" transform="rotate(-90, 50, 50)" />
</svg>


推荐阅读