Safari 不尊重 `transform-origin` SVG 属性

Max*_*kov 3 safari svg transform

我正在尝试使用属性构建 SVG transform。但是,虽然我的 SVG 在 Chrome 和 Firefox 中看起来符合预期,但在 Safari 中看起来却损坏了。看起来 Safari 不尊重transform-origin属性,总是应用transform类似transform-origin"0 0"值。

我需要对transform属性进行动画处理,并且需要生成的 SVG 在所有浏览器中看起来都相同。我尝试通过为transform-boxCSS 属性提供不同的值来解决这个问题,但没有成功。

该问题有解决方法吗?

下面是说明该问题的示例。所有图像应该看起来相同。它们在 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;
}
Run Code Online (Sandbox Code Playgroud)
<h1>1. Reference image</h1>

<figure>
  <svg width="200" height="200" 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-width="2"/>
    <line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-width="2"/>
    
    <circle cx="100" cy="100" r="75" stroke="none" fill="blue"/>
    <line x1="100" y1="25" x2="100" y2="175" stroke="rebeccapurple" stroke-width="1.5"/>
    <line x1="25" y1="100" x2="175" y2="100" stroke="rebeccapurple" stroke-width="1.5"/>
    
    <circle cx="100" cy="100" r="50" stroke="none" fill="red"/>
    <line x1="100" y1="50" x2="100" y2="150" stroke="rebeccapurple" stroke-width="1"/>
    <line x1="50" y1="100" x2="150" y2="100" stroke="rebeccapurple" stroke-width="1"/>
  
    <circle cx="100" cy="100" r="25" stroke="none" fill="yellow"/>
    <line x1="100" y1="75" x2="100" y2="125" stroke="rebeccapurple" stroke-width="0.5"/>
    <line x1="75" y1="100" x2="125" y2="100" stroke="rebeccapurple" stroke-width="0.5"/>
  </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>&lt;g&gt;</code> element</h1>

<figure>
  <svg width="200" height="200" 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-width="2"/>
        <line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-width="2"/>
      </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" width="200" height="200" 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>&lt;svg&gt;</code> has the same size as the outermost <code>&lt;svg&gt;</code>.</figcaption>
</figure>

<figure>
  <svg width="200" height="200" 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-width="2"/>
        <line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-width="2"/>
      </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" width="200" height="100" 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>&lt;svg&gt;</code> is centered in the outermost <code>&lt;svg&gt;</code> along single axis.</figcaption>
</figure>

<figure>
  <svg width="200" height="200" 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-width="2"/>
        <line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-width="2"/>
      </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" width="100" height="100" 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>&lt;svg&gt;</code> is centered in the outermost <code>&lt;svg&gt;</code> along both axes.</figcaption>
</figure>

<h1>3. <code>transform</code> applied to <code>&lt;svg&gt;</code> element</h1>

<figure>
  <svg width="200" height="200" viewBox="0 0 200 200">
    <defs>
      <svg id="target-svg-1" width="200" height="200" 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-width="2"/>
        <line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-width="2"/>
      </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" width="200" height="200" 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>&lt;svg&gt;</code> has the same size as the outermost <code>&lt;svg&gt;</code>.</figcaption>
</figure>

<figure>
  <svg width="200" height="200" viewBox="0 0 200 200">
    <defs>
      <svg id="target-svg-2a" width="200" height="200" 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-width="2"/>
        <line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-width="2"/>
      </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" width="200" height="100" 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>&lt;svg&gt;</code> is centered in the outermost <code>&lt;svg&gt;</code> along single axis.
    Transformed <code>&lt;svg&gt;</code> is shifted.
  </figcaption>
</figure>

<figure>
  <svg width="200" height="200" viewBox="0 0 200 200">
    <defs>
      <svg id="target-svg-2b" width="200" height="200" 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-width="2"/>
        <line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-width="2"/>
      </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" width="200" height="100" 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>&lt;svg&gt;</code> is centered in the outermost <code>&lt;svg&gt;</code> along single axis.
    <code>transform-origin</code> is shifted.
  </figcaption>
</figure>

<figure>
  <svg width="200" height="200" viewBox="0 0 200 200">
    <defs>
      <svg id="target-svg-3a" width="200" height="200" 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-width="2"/>
        <line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-width="2"/>
      </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" width="100" height="100" 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>&lt;svg&gt;</code> is centered in the outermost <code>&lt;svg&gt;</code> along both axes.
    Transformed <code>&lt;svg&gt;</code> is shifted.
  </figcaption>
</figure>

<figure>
  <svg width="200" height="200" viewBox="0 0 200 200">
    <defs>
      <svg id="target-svg-3b" width="200" height="200" 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-width="2"/>
        <line x1="0" y1="100" x2="200" y2="100" stroke="rebeccapurple" stroke-width="2"/>
      </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" width="100" height="100" 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>&lt;svg&gt;</code> is centered in the outermost <code>&lt;svg&gt;</code> along both axes.
    <code>transform-origin</code> is shifted.
  </figcaption>
</figure>
Run Code Online (Sandbox Code Playgroud)

Mic*_*any 8

Safari 实现了很少的 SVG 2 - 因此安全的方法是仅使用 SVG 1.1 功能进行跨浏览器(SVG 1.1 中没有转换源)。

在 SVG 1.1 中执行此操作的跨浏览器方式。就是变换/平移到原点,进行缩放,然后反向平移。就像是:

transform="translate(100 200) scale(0.5 0.5) translate(-100 -200)"
Run Code Online (Sandbox Code Playgroud)

使用这种技术,问题的片段将转换为:

transform="translate(100 200) scale(0.5 0.5) translate(-100 -200)"
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)