Safari 不尊重 `transform-origin` SVG 属性
Posted
技术标签:
【中文标题】Safari 不尊重 `transform-origin` SVG 属性【英文标题】:Safari doesn't respect `transform-origin` SVG attribute 【发布时间】:2021-07-07 11:07:57 【问题描述】:我正在尝试使用 transform
属性构建 SVG。但是,虽然我的 SVG 在 Chrome 和 Firefox 中看起来像预期的那样,但在 Safari 中看起来很糟糕。看起来 Safari 不尊重 transform-origin
属性,并且总是应用 transform
就像 transform-origin
具有 "0 0"
值。
我需要为 transform
属性设置动画,并且我需要生成的 SVG 在所有浏览器中看起来都一样。我尝试通过为transform-box
CSS 属性提供不同的值来解决此问题,但没有成功。
这个问题有解决办法吗?
以下是说明该问题的示例。所有图像应该看起来相同。它们在 Chrome 和 Firefox 中看起来相同,但在 Safari 中不同。
h1
font-family: sans-serif;
figure
border: thin #c0c0c0 solid;
display: inline-flex;
flex-flow: column;
padding: 5px;
max-width: 200px;
margin: auto;
figcaption
margin-top: 5px;
background-color: #222;
color: #fff;
font: smaller sans-serif;
padding: 3px;
text-align: center;
<h1>1. Reference image</h1>
<figure>
<svg viewBox="0 0 200 200">
<circle cx="100" cy="100" r="100" stroke="none" fill="black"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
<circle cx="100" cy="100" r="75" stroke="none" fill="blue"/>
<line x1="100" y1="25" x2="100" y2="175" stroke="rebeccapurple" stroke-/>
<line x1="25" y1="100" x2="175" y2="100" stroke="rebeccapurple" stroke-/>
<circle cx="100" cy="100" r="50" stroke="none" fill="red"/>
<line x1="100" y1="50" x2="100" y2="150" stroke="rebeccapurple" stroke-/>
<line x1="50" y1="100" x2="150" y2="100" stroke="rebeccapurple" stroke-/>
<circle cx="100" cy="100" r="25" stroke="none" fill="yellow"/>
<line x1="100" y1="75" x2="100" y2="125" stroke="rebeccapurple" stroke-/>
<line x1="75" y1="100" x2="125" y2="100" stroke="rebeccapurple" stroke-/>
</svg>
<figcaption>Figure 1. Reference image, <code>transform</code> is not used. All other images should look the same.</figcaption>
</figure>
<h1>2. <code>transform</code> applied to <code><g></code> element</h1>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<g id="target-g-1">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</g>
</defs>
<use href="#target-g-1" fill="black"/>
<use href="#target-g-1" fill="blue" transform="scale(0.75 0.75)" transform-origin="100 100"/>
<svg x="0" y="0" viewBox="0 0 200 200">
<use href="#target-g-1" fill="red" transform="scale(0.5 0.5)" transform-origin="100 100"/>
<use href="#target-g-1" fill="yellow" transform="scale(0.25 0.25)" transform-origin="100 100"/>
</svg>
</svg>
<figcaption>Figure 2-1. Nested <code><svg></code> has the same size as the outermost <code><svg></code>.</figcaption>
</figure>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<g id="target-g-2">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</g>
</defs>
<use href="#target-g-2" fill="black"/>
<use href="#target-g-2" fill="blue" transform="scale(0.75 0.75)" transform-origin="100 100"/>
<svg x="0" y="50" viewBox="0 0 200 100">
<use href="#target-g-2" fill="red" transform="scale(0.5 0.5)" transform-origin="100 0"/>
<use href="#target-g-2" fill="yellow" transform="scale(0.25 0.25)" transform-origin="100 33.3333"/>
</svg>
</svg>
<figcaption>Figure 2-2. Nested <code><svg></code> is centered in the outermost <code><svg></code> along single axis.</figcaption>
</figure>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<g id="target-g-3">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</g>
</defs>
<use href="#target-g-3" fill="black"/>
<use href="#target-g-3" fill="blue" transform="scale(0.75 0.75)" transform-origin="100 100"/>
<svg x="50" y="50" viewBox="0 0 100 100">
<use href="#target-g-3" fill="red" transform="scale(0.5 0.5)" transform-origin="0 0"/>
<use href="#target-g-3" fill="yellow" transform="scale(0.25 0.25)" transform-origin="33.3333 33.3333"/>
</svg>
</svg>
<figcaption>Figure 2-3. Nested <code><svg></code> is centered in the outermost <code><svg></code> along both axes.</figcaption>
</figure>
<h1>3. <code>transform</code> applied to <code><svg></code> element</h1>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<svg id="target-svg-1" viewBox="0 0 200 200" preserveAspectRatio="none">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</svg>
</defs>
<use href="#target-svg-1" fill="black"/>
<use href="#target-svg-1" fill="blue" transform="scale(0.75 0.75)" transform-origin="100 100"/>
<svg x="0" y="0" viewBox="0 0 200 200">
<use href="#target-svg-1" x="0" y="0" fill="red" transform="scale(0.5 0.5)" transform-origin="100 100"/>
<use href="#target-svg-1" x="0" y="0" fill="yellow" transform="scale(0.25 0.25)" transform-origin="100 100"/>
</svg>
</svg>
<figcaption>Figure 3-1. Nested <code><svg></code> has the same size as the outermost <code><svg></code>.</figcaption>
</figure>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<svg id="target-svg-2a" viewBox="0 0 200 200" preserveAspectRatio="none">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</svg>
</defs>
<use href="#target-svg-2a" x="0" y="0" fill="black"/>
<use href="#target-svg-2a" x="0" y="0" fill="blue" transform="scale(0.75 0.75)" transform-origin="100 100"/>
<svg x="0" y="50" viewBox="0 0 200 100">
<use href="#target-svg-2a" x="0" y="-50" fill="red" transform="scale(0.5 0.5)" transform-origin="100 50"/>
<use href="#target-svg-2a" x="0" y="-50" fill="yellow" transform="scale(0.25 0.25)" transform-origin="100 50"/>
</svg>
</svg>
<figcaption>
Figure 3-2a. Nested <code><svg></code> is centered in the outermost <code><svg></code> along single axis.
Transformed <code><svg></code> is shifted.
</figcaption>
</figure>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<svg id="target-svg-2b" viewBox="0 0 200 200" preserveAspectRatio="none">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</svg>
</defs>
<use href="#target-svg-2b" x="0" y="0" fill="black"/>
<use href="#target-svg-2b" x="0" y="0" fill="blue" transform="scale(0.75 0.75)" transform-origin="100 100"/>
<svg x="0" y="50" viewBox="0 0 200 100">
<use href="#target-svg-2b" x="0" y="0" fill="red" transform="scale(0.5 0.5)" transform-origin="100 0"/>
<use href="#target-svg-2b" x="0" y="0" fill="yellow" transform="scale(0.25 0.25)" transform-origin="100 33.333333"/>
</svg>
</svg>
<figcaption>
Figure 3-2b. Nested <code><svg></code> is centered in the outermost <code><svg></code> along single axis.
<code>transform-origin</code> is shifted.
</figcaption>
</figure>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<svg id="target-svg-3a" viewBox="0 0 200 200" preserveAspectRatio="none">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</svg>
</defs>
<use href="#target-svg-3a" fill="black"/>
<use href="#target-svg-3a" fill="blue" transform="scale(0.75 0.75)" transform-origin="100 100"/>
<svg x="50" y="50" viewBox="0 0 100 100">
<use href="#target-svg-3a" x="-50" y="-50" fill="red" transform="scale(0.5 0.5)" transform-origin="50 50"/>
<use href="#target-svg-3a" x="-50" y="-50" fill="yellow" transform="scale(0.25 0.25)" transform-origin="50 50"/>
</svg>
</svg>
<figcaption>
Figure 3-3a. Nested <code><svg></code> is centered in the outermost <code><svg></code> along both axes.
Transformed <code><svg></code> is shifted.
</figcaption>
</figure>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<svg id="target-svg-3b" viewBox="0 0 200 200" preserveAspectRatio="none">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</svg>
</defs>
<use href="#target-svg-3b" fill="black"/>
<use href="#target-svg-3b" fill="blue" transform="scale(0.75 0.75)" transform-origin="100 100"/>
<svg x="50" y="50" viewBox="0 0 100 100">
<use href="#target-svg-3b" x="0" y="0" fill="red" transform="scale(0.5 0.5)" transform-origin="0 0"/>
<use href="#target-svg-3b" x="0" y="0" fill="yellow" transform="scale(0.25 0.25)" transform-origin="33.333333 33.333333"/>
</svg>
</svg>
<figcaption>
Figure 3-3b. Nested <code><svg></code> is centered in the outermost <code><svg></code> along both axes.
<code>transform-origin</code> is shifted.
</figcaption>
</figure>
【问题讨论】:
这听起来像是 WebKit 中的一个错误,应该报告 bugs.webkit.org — 因为 Safari 确实声称支持transform-origin
。
在技术预览中支持...。所以不需要错误报告。
@Kaiido 我刚刚在 Safari Technology Preview Release 123(Safari 14.2,WebKit 15612.1.7.10)中对其进行了测试,但它不能正常工作。
@sideshowbarker 我发现有一个现有的 Safari 错误 bugs.webkit.org/show_bug.cgi?id=201854 于 2019 年 10 月打开。必须在 caniuse.com 上提及
最新TP为16612.1.7.10
【参考方案1】:
Safari 几乎没有实现 SVG 2 - 所以安全的方法是只使用 SVG 1.1 的跨浏览器功能(SVG 1.1 中没有转换源)。
在 SVG 1.1 中实现这一点的跨浏览器方式。是转换/平移到原点,进行缩放,然后反转平移。比如:
transform="translate(100 200) scale(0.5 0.5) translate(-100 -200)"
使用这种技术,问题中的 sn-p 将转换为:
h1
font-family: sans-serif;
figure
border: thin #c0c0c0 solid;
display: inline-flex;
flex-flow: column;
padding: 5px;
max-width: 200px;
margin: auto;
figcaption
margin-top: 5px;
background-color: #222;
color: #fff;
font: smaller sans-serif;
padding: 3px;
text-align: center;
<h1>1. Reference image</h1>
<figure>
<svg viewBox="0 0 200 200">
<circle cx="100" cy="100" r="100" stroke="none" fill="black"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
<circle cx="100" cy="100" r="75" stroke="none" fill="blue"/>
<line x1="100" y1="25" x2="100" y2="175" stroke="rebeccapurple" stroke-/>
<line x1="25" y1="100" x2="175" y2="100" stroke="rebeccapurple" stroke-/>
<circle cx="100" cy="100" r="50" stroke="none" fill="red"/>
<line x1="100" y1="50" x2="100" y2="150" stroke="rebeccapurple" stroke-/>
<line x1="50" y1="100" x2="150" y2="100" stroke="rebeccapurple" stroke-/>
<circle cx="100" cy="100" r="25" stroke="none" fill="yellow"/>
<line x1="100" y1="75" x2="100" y2="125" stroke="rebeccapurple" stroke-/>
<line x1="75" y1="100" x2="125" y2="100" stroke="rebeccapurple" stroke-/>
</svg>
<figcaption>Figure 1. Reference image, <code>transform</code> is not used. All other images should look the same.</figcaption>
</figure>
<h1>2. <code>transform</code> applied to <code><g></code> element</h1>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<g id="target-g-1">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</g>
</defs>
<use href="#target-g-1" fill="black"/>
<use href="#target-g-1" fill="blue" transform="translate(100 100) scale(0.75 0.75) translate(-100 -100)"/>
<svg x="0" y="0" viewBox="0 0 200 200">
<use href="#target-g-1" fill="red" transform="translate(100 100) scale(0.5 0.5) translate(-100 -100)"/>
<use href="#target-g-1" fill="yellow" transform="translate(100 100) scale(0.25 0.25) translate(-100 -100)"/>
</svg>
</svg>
<figcaption>Figure 2-1. Nested <code><svg></code> has the same size as the outermost <code><svg></code>.</figcaption>
</figure>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<g id="target-g-2">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</g>
</defs>
<use href="#target-g-2" fill="black"/>
<use href="#target-g-2" fill="blue" transform="translate(100 100) scale(0.75 0.75) translate(-100 -100)"/>
<svg x="0" y="50" viewBox="0 0 200 100">
<use href="#target-g-2" fill="red" transform="translate(100 0) scale(0.5 0.5) translate(-100 -0)"/>
<use href="#target-g-2" fill="yellow" transform="translate(100 33.3333) scale(0.25 0.25) translate(-100 -33.3333)"/>
</svg>
</svg>
<figcaption>Figure 2-2. Nested <code><svg></code> is centered in the outermost <code><svg></code> along single axis.</figcaption>
</figure>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<g id="target-g-3">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</g>
</defs>
<use href="#target-g-3" fill="black"/>
<use href="#target-g-3" fill="blue" transform="translate(100 100) scale(0.75 0.75) translate(-100 -100)"/>
<svg x="50" y="50" viewBox="0 0 100 100">
<use href="#target-g-3" fill="red" transform="translate(0 0) scale(0.5 0.5) translate(-0 -0)"/>
<use href="#target-g-3" fill="yellow" transform="translate(33.3333 33.3333) scale(0.25 0.25) translate(-33.3333 -33.3333)"/>
</svg>
</svg>
<figcaption>Figure 2-3. Nested <code><svg></code> is centered in the outermost <code><svg></code> along both axes.</figcaption>
</figure>
<h1>3. <code>transform</code> applied to <code><svg></code> element</h1>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<svg id="target-svg-1" viewBox="0 0 200 200" preserveAspectRatio="none">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</svg>
</defs>
<use href="#target-svg-1" fill="black"/>
<use href="#target-svg-1" fill="blue" transform="translate(100 100) scale(0.75 0.75) translate(-100 -100)"/>
<svg x="0" y="0" viewBox="0 0 200 200">
<use href="#target-svg-1" x="0" y="0" fill="red" transform="translate(100 100) scale(0.5 0.5) translate(-100 -100)"/>
<use href="#target-svg-1" x="0" y="0" fill="yellow" transform="translate(100 100) scale(0.25 0.25) translate(-100 -100)"/>
</svg>
</svg>
<figcaption>Figure 3-1. Nested <code><svg></code> has the same size as the outermost <code><svg></code>.</figcaption>
</figure>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<svg id="target-svg-2a" viewBox="0 0 200 200" preserveAspectRatio="none">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</svg>
</defs>
<use href="#target-svg-2a" x="0" y="0" fill="black"/>
<use href="#target-svg-2a" x="0" y="0" fill="blue" transform="translate(100 100) scale(0.75 0.75) translate(-100 -100)"/>
<svg x="0" y="50" viewBox="0 0 200 100">
<use href="#target-svg-2a" x="0" y="-50" fill="red" transform="translate(100 50) scale(0.5 0.5) translate(-100 -50)"/>
<use href="#target-svg-2a" x="0" y="-50" fill="yellow" transform="translate(100 50) scale(0.25 0.25) translate(-100 -50)"/>
</svg>
</svg>
<figcaption>
Figure 3-2a. Nested <code><svg></code> is centered in the outermost <code><svg></code> along single axis.
Transformed <code><svg></code> is shifted.
</figcaption>
</figure>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<svg id="target-svg-2b" viewBox="0 0 200 200" preserveAspectRatio="none">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</svg>
</defs>
<use href="#target-svg-2b" x="0" y="0" fill="black"/>
<use href="#target-svg-2b" x="0" y="0" fill="blue" transform="translate(100 100) scale(0.75 0.75) translate(-100 -100)"/>
<svg x="0" y="50" viewBox="0 0 200 100">
<use href="#target-svg-2b" x="0" y="0" fill="red" transform="translate(100 0) scale(0.5 0.5) translate(-100 0)"/>
<use href="#target-svg-2b" x="0" y="0" fill="yellow" transform="translate(100 33.33333) scale(0.25 0.25) translate(-100 -33.33333)"/>
</svg>
</svg>
<figcaption>
Figure 3-2b. Nested <code><svg></code> is centered in the outermost <code><svg></code> along single axis.
<code>transform-origin</code> is shifted.
</figcaption>
</figure>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<svg id="target-svg-3a" viewBox="0 0 200 200" preserveAspectRatio="none">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</svg>
</defs>
<use href="#target-svg-3a" fill="black"/>
<use href="#target-svg-3a" fill="blue" transform="translate(100 100) scale(0.75 0.75) translate(-100 -100)"/>
<svg x="50" y="50" viewBox="0 0 100 100">
<use href="#target-svg-3a" x="-50" y="-50" fill="red" transform="translate(50 50) scale(0.5 0.5) translate(-50 -50)"/>
<use href="#target-svg-3a" x="-50" y="-50" fill="yellow" transform="translate(50 50) scale(0.25 0.25) translate(-50 -50)"/>
</svg>
</svg>
<figcaption>
Figure 3-3a. Nested <code><svg></code> is centered in the outermost <code><svg></code> along both axes.
Transformed <code><svg></code> is shifted.
</figcaption>
</figure>
<figure>
<svg viewBox="0 0 200 200">
<defs>
<svg id="target-svg-3b" viewBox="0 0 200 200" preserveAspectRatio="none">
<circle cx="100" cy="100" r="100" stroke="none"/>
<line x1="100" y1="0" x2="100" y2="200" stroke="rebeccapurple" stroke-/>
<line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-/>
</svg>
</defs>
<use href="#target-svg-3b" fill="black"/>
<use href="#target-svg-3b" fill="blue" transform="translate(100 100) scale(0.75 0.75) translate(-100 -100)"/>
<svg x="50" y="50" viewBox="0 0 100 100">
<use href="#target-svg-3b" x="0" y="0" fill="red" transform="scale(0.5 0.5)"/>
<use href="#target-svg-3b" x="0" y="0" fill="yellow" transform="translate(33.333333 33.333333) scale(0.25 0.25) translate(-33.333333 -33.333333)"/>
</svg>
</svg>
<figcaption>
Figure 3-3b. Nested <code><svg></code> is centered in the outermost <code><svg></code> along both axes.
<code>transform-origin</code> is shifted.
</figcaption>
</figure>
【讨论】:
以上是关于Safari 不尊重 `transform-origin` SVG 属性的主要内容,如果未能解决你的问题,请参考以下文章
Flexbox 不尊重 overflow-x: hidden on body (Safari / iOS webkit)
如何在 Firefox 中不尊重纵横比的情况下缩放 SVG 背景图像?