动画不适用于计算的 CSS 变量

Animation not working with calculated CSS variables

我想用 CSS var.

为 SVG 圆的 属性 stroke-dasharray 设置动画

在绿色中,动画是正确的并且动画连续且流畅
在红色中,动画不正确,因为它以 .

动画

我认为计算的 CSS 变量有问题,但我不明白是什么。
我们可以看到带有正方形的动画是正确的,即使它使用计算的 CSS var.

body {
  display: flex;
}

svg {
  width: 200px;
  height: 200px;
}

circle.good {
  stroke: green;
  stroke-width: 5;
  animation: good-dash 2s ease-in-out infinite;
}

circle.bad {
  stroke: red;
  stroke-width: 5;
  animation: bad-dash 2s ease-in-out infinite;
  --stroke-dasharray: 10;
}

.square {
  width: 200px;
  height: 200px;
  background-color: green;
  animation: good-roll 2s infinite ease-in-out both;
  position: relative;
  --left: 1;
}

@keyframes good-dash {
  0% {
    stroke-dasharray: 1, 10;
  }
  50% {
    stroke-dasharray: 1, 5;
  }
  100% {
    stroke-dasharray: 1, 10;
  }
}

@keyframes bad-dash {
  0% {
    stroke-dasharray: 1, var(--stroke-dasharray);
  }
  50% {
    stroke-dasharray: 1, calc(var(--stroke-dasharray) / 2);
  }
  100% {
    stroke-dasharray: 1, var(--stroke-dasharray);
  }
}

@keyframes good-roll {
  0% {
    left: calc(var(--left) * 1px);
  }
  50% {
    left: calc(var(--left) * 50px);
  }
  100% {
    left: calc(var(--left) * 1px);
  }
}
<svg viewBox="25 25 50 50">
  <circle class="good" cx="50" cy="50" r="20" fill="none"/>
</svg>
<svg viewBox="25 25 50 50">
  <circle class="bad" cx="50" cy="50" r="20" fill="none"/>
</svg>
<div class="square"></div>

计算表达式中的单位是强制性的,涉及的东西并非自然无单位,实际上您应该尝试在任何地方使用它们,因为 CSS 大多数情况下都需要它们。

  • 不透明度是一个真正的无单位属性,它只是一个<number> in the specification

  • stroke-dasharray 然而它不是无单位的 <length><percentage>

  • SVG 有一个特殊的 'legacy' 规则,该规则表明一些 SVG 独有的通常需要单位的属性可以在没有单位的情况下编写。

当涉及到计算表达式时,允许省略单位的特定 SVG 规则并不适用并且 everything that should have a unit, must have a unit。 Chrome 目前尚未实施此要求,但我希望他们会在某个时候实施。

body {
  display: flex;
}

svg {
  width: 200px;
  height: 200px;
}

circle.good {
  stroke: green;
  stroke-width: 5;
  animation: good-dash 2s ease-in-out infinite;
}

circle.bad {
  stroke: red;
  stroke-width: 5;
  animation: bad-dash 2s ease-in-out infinite;
  --stroke-dasharray: 10px;
}

.square {
  width: 200px;
  height: 200px;
  background-color: green;
  animation: good-roll 2s infinite ease-in-out both;
  position: relative;
  --left: 1;
}

@keyframes good-dash {
  0% {
    stroke-dasharray: 1, 10;
  }
  50% {
    stroke-dasharray: 1, 5;
  }
  100% {
    stroke-dasharray: 1, 10;
  }
}

@keyframes bad-dash {
  0% {
    stroke-dasharray: 1px, var(--stroke-dasharray);
  }
  50% {
    stroke-dasharray: 1px, calc(var(--stroke-dasharray) / 2);
  }
  100% {
    stroke-dasharray: 1px, var(--stroke-dasharray);
  }
}

@keyframes good-roll {
  0% {
    left: calc(var(--left) * 1px);
  }
  50% {
    left: calc(var(--left) * 50px);
  }
  100% {
    left: calc(var(--left) * 1px);
  }
}
<svg viewBox="25 25 50 50">
  <circle class="good" cx="50" cy="50" r="20" fill="none"/>
</svg>
<svg viewBox="25 25 50 50">
  <circle class="bad" cx="50" cy="50" r="20" fill="none"/>
</svg>
<div class="square"></div>