SVG 掩码翻译在 Chromium 浏览器上滞后

SVG mask translation lags on Chromium browsers

我是动画 SVG 合集的作者 theme-toggles。我注意到任何涉及翻译掩码的内容在 chromium 浏览器上都非常不稳定,但在 Firefox 上却很好。

有问题的开关是 Classic and Expand

动画似乎受到限制,可能是因为 Chromium 认为遮罩不在视野范围内。虽然这个问题似乎在大多数时间都存在,但在某些情况下他们确实在 Chromium 上工作,但我无法解释为什么他们有时会工作。

如能帮助解决此问题,我们将不胜感激。我在此处描述的 中发现了类似的问题,但尚未完全找出解决方案的原因。

.theme-toggle {
  font-size: 10rem;
}
<link href="https://cdn.jsdelivr.net/npm/theme-toggles@3.5.1/css/classic.min.css" rel="stylesheet"/>
<label class="theme-toggle">
  <input type="checkbox" />
  <span class="theme-toggle-sr">Toggle theme</span>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    width="1em"
    height="1em"
    fill="currentColor"
    stroke-linecap="round"
    class="theme-toggle__classic"
    viewBox="0 0 32 32"
  >
    <mask id="theme-toggle__classic__cutout" color="#000">
      <path fill="#fff" d="M0 0h32v32H0z" />
      <circle cx="34" cy="2" r="8" />
    </mask>
    <circle
      cx="16"
      cy="16"
      r="9.34"
      mask="url(#theme-toggle__classic__cutout)"
    />
    <g
      stroke="currentColor"
      class="theme-toggle__classic__sun-rays"
      mask="url(#theme-toggle__classic__cutout)"
    >
      <path d="M16 5.5v-4" />
      <path d="M16 30.5v-4" />
      <path d="M1.5 16h4" />
      <path d="M26.5 16h4" />
      <path d="m23.4 8.6 2.8-2.8" />
      <path d="m5.7 26.3 2.9-2.9" />
      <path d="m5.8 5.8 2.8 2.8" />
      <path d="m23.4 23.4 2.9 2.9" />
    </g>
  </svg>
</label>

这似乎至少可以提高 Chromium 的性能。我做了三处改动:

  1. 将面具换成clip-path
  2. 仅将 clip-path 应用于包含圆和射线的父组一次
  3. 这一个有所不同:不转换 transform,而是直接转换 d 路径数据。对于 Chrome (99) 和 Firefox (98),您现在可以编写 CSS 语法 d: path('...') 并为路径数据设置动画。它不适用于 Safari。

.theme-toggle.theme-toggle--reversed .theme-toggle__classic {
    transform: scale(-1,1)
}

.theme-toggle {
    --theme-toggle__classic--duration: 750ms
}

.theme-toggle__classic * {
    transition-property: opacity,transform,d;
    transition-timing-function: cubic-bezier(0,0,0.15,1.25);
    transform-origin: center;
    transition-duration: var(--theme-toggle__classic--duration);
    transition-delay: calc(var(--theme-toggle__classic--duration) / 5);
}

.theme-toggle__classic #theme-toggle__classic__cutout path {
    transition-delay: 0s;
    d: path('M0-10h34v4a8 8 0 108 8h1v32h-43z');
}

.theme-toggle input[type=checkbox]:checked~.theme-toggle__classic .theme-toggle__classic__sun-rays *,
.theme-toggle--toggled:not(label).theme-toggle .theme-toggle__classic .theme-toggle__classic__sun-rays * {
    transform: scale(.5) rotate(45deg);
    opacity: 0;
    transition-delay: 0s
}

.theme-toggle input[type=checkbox]:checked~.theme-toggle__classic #theme-toggle__classic__cutout path,
.theme-toggle--toggled:not(label).theme-toggle .theme-toggle__classic #theme-toggle__classic__cutout path {
    d: path('M-11 0h34v4a8 8 0 108 8h1v32h-43z');
    transition-delay: calc(var(--theme-toggle__classic--duration) / 5)
}

button.theme-toggle,label.theme-toggle {
    border: none;
    background: 0 0;
    cursor: pointer
}

button.theme-toggle input[type=checkbox],label.theme-toggle input[type=checkbox] {
    display: none
}

button.theme-toggle .theme-toggle-sr,label.theme-toggle .theme-toggle-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
    border-width: 0
}

.theme-toggle {
  font-size: 10rem;
}
<label class="theme-toggle">
  <input type="checkbox" />
  <span class="theme-toggle-sr">Toggle theme</span>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    width="1em"
    height="1em"
    fill="currentColor"
    stroke-linecap="round"
    class="theme-toggle__classic"
    viewBox="0 0 32 32"
  >
    <clipPath id="theme-toggle__classic__cutout">
      <path />
    </clipPath>
    <g clip-path="url(#theme-toggle__classic__cutout)">
      <circle cx="16" cy="16" r="9.34" />
      <g
        stroke="currentColor"
        class="theme-toggle__classic__sun-rays"
      >
        <path d="M16 5.5v-4" />
        <path d="M16 30.5v-4" />
        <path d="M1.5 16h4" />
        <path d="M26.5 16h4" />
        <path d="m23.4 8.6 2.8-2.8" />
        <path d="m5.7 26.3 2.9-2.9" />
        <path d="m5.8 5.8 2.8 2.8" />
        <path d="m23.4 23.4 2.9 2.9" />
      </g>
    </g>
  </svg>
</label>