问题描述
我想使用 CSS var 为 SVG 圆的属性 stroke-dasharray 设置动画。
绿色表示动画正确且动画连续流畅。
红色表示动画不正确,因为它按步骤制作动画。
我认为计算的 CSS 变量有问题,但我不明白是什么。
我们可以看到带有正方形的动画即使使用了计算的 CSS 变量也是正确的。
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>
解决方法
在涉及并非自然无单位的东西的 calc 表达式中单位是强制性的,实际上您应该尝试在任何地方使用它们,因为 CSS 主要需要它们。
-
opacity 是一个真正无单位的属性,它只是一个
<number>
in the specification。 -
stroke-dasharray 然而不是无单位的,它要么是一个
<length>
要么是一个<percentage>
-
SVG 有一个特殊的“遗留”规则,即 SVG 特有的一些通常需要单位的属性可以不用单位编写。
当涉及到 calc 表达式时,虽然允许省略单位的特定 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>