每次重复的 SVG 动画延迟
SVG animation delay on each repetition
我想为 SVG 动画循环的每次迭代添加延迟。这是一个简单的例子。
<svg xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
<circle cx="50" cy="50" r="15" fill="blue">
<animate id="op" attributeType="CSS" attributeName="opacity"
from="1" to="0" dur="3s" repeatCount="indefinite" />
</circle>
</svg>
使用begin
只会延迟第一次迭代,那么,有没有办法延迟每次迭代?
您可以将 SMIL 动画元素的 end
事件添加到 begin
属性。
此外,您可以向此 begin
属性添加多个值,以 ;
分隔:
<svg xmlns="http://www.w3.org/2000/svg" width="300px" height="100px">
<circle cx="50" cy="50" r="15" fill="blue">
<animate id="op" attributeType="CSS" attributeName="opacity"
from="1" to="0" dur="3s" begin="3s;op.end+3s" />
</circle>
</svg>
我认为您正在寻找的是 svg 的 additive/accumulative 属性。这是我从 css tricks
得到的一个例子
svg {
border: 3px solid #eee;
display: block;
margin: 1em auto;
}
<svg width="500" height="100">
<circle id="orange-circle" r="30" cx="50" cy="50" fill="orange" />
<animate xlink:href="#orange-circle" attributeName="cx" from="0" to="100" additive="sum" repeatCount="3" calcMode="spline" keyTimes="0;1" keySplines=".42 0 1 1" dur="1s" begin="click" fill="freeze" />
</svg>
事实上这里有一个更好的例子(相同来源)
svg {
border: 3px solid #eee;
display: block;
margin: 1em auto;
}
<svg width="500" height="150">
<style>
rect {
-moz-transform-origin: 75px 75px;
transform-origin: 50% 50%;
}
</style>
<rect id="deepPink-rectangle" width="50" height="50" x="50" y="50" fill="deepPink" />
<animateTransform
xlink:href="#deepPink-rectangle"
attributeName="transform"
attributeType="XML"
type="rotate"
from="0 75 75"
to="360 75 75"
dur="2s"
begin="0s; 5s; 9s; 17s;"
end="2s; 8s; 15s; 25s;"
fill="freeze"
restart="whenNotActive"
/>
</svg>
定义虚拟循环并设置相对开始时间。看
How to make SVG Loop Animation?
<svg xmlns="http://www.w3.org/2000/svg" width="300px" height="200px">
<rect>
<animate id="o1" begin="0;o1.end" dur="10s"
attributeName="visibility" from="hide" to="hide"/>
</rect>
<circle fill="orange" cx="-50" cy="100" r="20">
<animate begin="o1.begin"
attributeName="cx" from="250" to="50" dur="5.05s"/>
</circle>
<circle fill="blue" cx="150" cy="100" r="50" />
<circle fill="orange" cx="-50" cy="100" r="20">
<animate begin="o1.begin+5s"
attributeName="cx" from="50" to="250" dur="5.05s"/>
</circle>
</svg>
下面是 "closing eyes" 的示例...感谢此线程中的建议。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 16"><g>
<g >
<ellipse cx="9.45" cy="7.7" rx="0.96" ry="0.96" style="stroke: none; fill: black;">
<animate id="op" attributeName="ry" attributeType="XML"
to="0.1"
begin="3s;op.end+3s" dur="0.15s"
fill="remove" repeatCount="2"
/>
</ellipse>
<ellipse cx="14.6" cy="7.8" rx="0.8" ry="0.8" style="stroke: none; fill: black;">
<animate id="op" attributeName="ry" attributeType="XML"
to="0.1"
begin="3s;op.end+3s" dur="0.15s"
fill="remove" repeatCount="2"
/>
</ellipse>
</g>
</svg>
这是 Danjiro Daiwa 示例的更详细版本,没有隐藏矩形来同步动画,也没有诉诸将橙色圆圈设置在可见区域之外来隐藏它们,而是使用 opacity="0"
。同时有四个动画运行,a1/a2移动,o1/o2移动时隐藏橙色分身圈behind/over蓝色圈,r1- r4 改变半径 r
和 f1-f4 改变 fill
颜色。
<svg xmlns="http://www.w3.org/2000/svg" width="300px" height="200px">
<circle fill="#f70" cx="0" cy="100" r="20" opacity="0">
<animate id="a1" attributeName="cx" begin="0s;a2.end" from="250" to="50" dur="3s"/>
<animate id="o1" attributeName="opacity" begin="a1.begin" end="a1.end" from="1" to="1"/>
<animate id="r1" attributeName="r" begin="a1.begin" from="20" to="15" dur="1.5s"/>
<animate id="r2" attributeName="r" begin="r1.end" from="15" to="20" dur="1.5s"/>
<animate id="f1" attributeName="fill" begin="a1.begin" from="#f70" to="#c00" dur="1.5s"/>
<animate id="f2" attributeName="fill" begin="f1.end" from="#c00" to="#f70" dur="1.5s"/>
</circle>
<circle fill="blue" cx="150" cy="100" r="50" />
<circle fill="#f90" cx="0" cy="100" r="20" opacity="0">
<animate id="a2" attributeName="cx" begin="a1.end" from="50" to="250" dur="2s"/>
<animate id="o2" attributeName="opacity" begin="a2.begin" end="a2.end" from="1" to="1"/>
<animate id="r3" attributeName="r" begin="a2.begin" from="20" to="25" dur="1s"/>
<animate id="r4" attributeName="r" begin="r3.end" from="25" to="20" dur="1s"/>
<animate id="f3" attributeName="fill" begin="a2.begin" from="#f70" to="#ff0" dur="1s"/>
<animate id="f4" attributeName="fill" begin="f3.end" from="#ff0" to="#f70" dur="1s"/>
</circle>
</svg>
如果你想让你的动画交替出现(类似于animation-direction: alternate;
does in CSS), and you want to have a different delay for the initial/start/first repetition vs subsequent repetitions, here I provide two workarounds. See this GitHub issue in SVG Working Group repo。
解决方案 1:使用两个动画元素
<circle fill="#f5ca20" r="5" cx="12" cy="12">
<animate id="anim1" attributeName="r" dur="1s" fill="freeze" begin="3s; anim2.end + 5s" to="10" keyTimes="0; 1" calcMode="spline" keySplines="0.37, 0, 0.63, 1"/>
<animate id="anim2" attributeName="r" dur="1s" fill="freeze" begin="anim1.end + 5s" to="5" keyTimes="0; 1" calcMode="spline" keySplines="0.37, 0, 0.63, 1"/>
</circle>
解决方案 2:使用 values
和 keyTimes
属性的组合
<circle fill="#f5ca20" r="5" cx="12" cy="12">
<animate attributeName="r" dur="12s" begin="3s" values="5; 10; 10; 5; 5" keyTimes="0; 0.083; 0.5; 0.583; 1" repeatDur="indefinite" calcMode="spline" keySplines="0.37, 0, 0.63, 1; 0, 0, 1, 1; 0.37, 0, 0.63, 1; 0, 0, 1, 1"/>
</circle>
在这种方法中,您应该计算动画的总持续时间加上延迟并将其分配给 dur
,并计算持续时间的 keyTimes
值。对于我的示例,总持续时间为 12s
,时间 3s 1s 5s 1s 5s 映射到 keyTimes="0; 0.083; 0.5; 0.583; 1"
。
示例注释
calcMode="..."
和 keySplines="..."
是可选的(它们指定 timing interpolation)
- 初始动画延迟为3秒
- 动画(收缩和展开)每个需要 1 秒
- 开始到shrink/expand之前的延迟是5秒
以上两者都会产生以下结果:
我想为 SVG 动画循环的每次迭代添加延迟。这是一个简单的例子。
<svg xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
<circle cx="50" cy="50" r="15" fill="blue">
<animate id="op" attributeType="CSS" attributeName="opacity"
from="1" to="0" dur="3s" repeatCount="indefinite" />
</circle>
</svg>
使用begin
只会延迟第一次迭代,那么,有没有办法延迟每次迭代?
您可以将 SMIL 动画元素的 end
事件添加到 begin
属性。
此外,您可以向此 begin
属性添加多个值,以 ;
分隔:
<svg xmlns="http://www.w3.org/2000/svg" width="300px" height="100px">
<circle cx="50" cy="50" r="15" fill="blue">
<animate id="op" attributeType="CSS" attributeName="opacity"
from="1" to="0" dur="3s" begin="3s;op.end+3s" />
</circle>
</svg>
我认为您正在寻找的是 svg 的 additive/accumulative 属性。这是我从 css tricks
得到的一个例子svg {
border: 3px solid #eee;
display: block;
margin: 1em auto;
}
<svg width="500" height="100">
<circle id="orange-circle" r="30" cx="50" cy="50" fill="orange" />
<animate xlink:href="#orange-circle" attributeName="cx" from="0" to="100" additive="sum" repeatCount="3" calcMode="spline" keyTimes="0;1" keySplines=".42 0 1 1" dur="1s" begin="click" fill="freeze" />
</svg>
事实上这里有一个更好的例子(相同来源)
svg {
border: 3px solid #eee;
display: block;
margin: 1em auto;
}
<svg width="500" height="150">
<style>
rect {
-moz-transform-origin: 75px 75px;
transform-origin: 50% 50%;
}
</style>
<rect id="deepPink-rectangle" width="50" height="50" x="50" y="50" fill="deepPink" />
<animateTransform
xlink:href="#deepPink-rectangle"
attributeName="transform"
attributeType="XML"
type="rotate"
from="0 75 75"
to="360 75 75"
dur="2s"
begin="0s; 5s; 9s; 17s;"
end="2s; 8s; 15s; 25s;"
fill="freeze"
restart="whenNotActive"
/>
</svg>
定义虚拟循环并设置相对开始时间。看 How to make SVG Loop Animation?
<svg xmlns="http://www.w3.org/2000/svg" width="300px" height="200px">
<rect>
<animate id="o1" begin="0;o1.end" dur="10s"
attributeName="visibility" from="hide" to="hide"/>
</rect>
<circle fill="orange" cx="-50" cy="100" r="20">
<animate begin="o1.begin"
attributeName="cx" from="250" to="50" dur="5.05s"/>
</circle>
<circle fill="blue" cx="150" cy="100" r="50" />
<circle fill="orange" cx="-50" cy="100" r="20">
<animate begin="o1.begin+5s"
attributeName="cx" from="50" to="250" dur="5.05s"/>
</circle>
</svg>
下面是 "closing eyes" 的示例...感谢此线程中的建议。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 16"><g>
<g >
<ellipse cx="9.45" cy="7.7" rx="0.96" ry="0.96" style="stroke: none; fill: black;">
<animate id="op" attributeName="ry" attributeType="XML"
to="0.1"
begin="3s;op.end+3s" dur="0.15s"
fill="remove" repeatCount="2"
/>
</ellipse>
<ellipse cx="14.6" cy="7.8" rx="0.8" ry="0.8" style="stroke: none; fill: black;">
<animate id="op" attributeName="ry" attributeType="XML"
to="0.1"
begin="3s;op.end+3s" dur="0.15s"
fill="remove" repeatCount="2"
/>
</ellipse>
</g>
</svg>
这是 Danjiro Daiwa 示例的更详细版本,没有隐藏矩形来同步动画,也没有诉诸将橙色圆圈设置在可见区域之外来隐藏它们,而是使用 opacity="0"
。同时有四个动画运行,a1/a2移动,o1/o2移动时隐藏橙色分身圈behind/over蓝色圈,r1- r4 改变半径 r
和 f1-f4 改变 fill
颜色。
<svg xmlns="http://www.w3.org/2000/svg" width="300px" height="200px">
<circle fill="#f70" cx="0" cy="100" r="20" opacity="0">
<animate id="a1" attributeName="cx" begin="0s;a2.end" from="250" to="50" dur="3s"/>
<animate id="o1" attributeName="opacity" begin="a1.begin" end="a1.end" from="1" to="1"/>
<animate id="r1" attributeName="r" begin="a1.begin" from="20" to="15" dur="1.5s"/>
<animate id="r2" attributeName="r" begin="r1.end" from="15" to="20" dur="1.5s"/>
<animate id="f1" attributeName="fill" begin="a1.begin" from="#f70" to="#c00" dur="1.5s"/>
<animate id="f2" attributeName="fill" begin="f1.end" from="#c00" to="#f70" dur="1.5s"/>
</circle>
<circle fill="blue" cx="150" cy="100" r="50" />
<circle fill="#f90" cx="0" cy="100" r="20" opacity="0">
<animate id="a2" attributeName="cx" begin="a1.end" from="50" to="250" dur="2s"/>
<animate id="o2" attributeName="opacity" begin="a2.begin" end="a2.end" from="1" to="1"/>
<animate id="r3" attributeName="r" begin="a2.begin" from="20" to="25" dur="1s"/>
<animate id="r4" attributeName="r" begin="r3.end" from="25" to="20" dur="1s"/>
<animate id="f3" attributeName="fill" begin="a2.begin" from="#f70" to="#ff0" dur="1s"/>
<animate id="f4" attributeName="fill" begin="f3.end" from="#ff0" to="#f70" dur="1s"/>
</circle>
</svg>
如果你想让你的动画交替出现(类似于animation-direction: alternate;
does in CSS), and you want to have a different delay for the initial/start/first repetition vs subsequent repetitions, here I provide two workarounds. See this GitHub issue in SVG Working Group repo。
解决方案 1:使用两个动画元素
<circle fill="#f5ca20" r="5" cx="12" cy="12">
<animate id="anim1" attributeName="r" dur="1s" fill="freeze" begin="3s; anim2.end + 5s" to="10" keyTimes="0; 1" calcMode="spline" keySplines="0.37, 0, 0.63, 1"/>
<animate id="anim2" attributeName="r" dur="1s" fill="freeze" begin="anim1.end + 5s" to="5" keyTimes="0; 1" calcMode="spline" keySplines="0.37, 0, 0.63, 1"/>
</circle>
解决方案 2:使用 values
和 keyTimes
属性的组合
<circle fill="#f5ca20" r="5" cx="12" cy="12">
<animate attributeName="r" dur="12s" begin="3s" values="5; 10; 10; 5; 5" keyTimes="0; 0.083; 0.5; 0.583; 1" repeatDur="indefinite" calcMode="spline" keySplines="0.37, 0, 0.63, 1; 0, 0, 1, 1; 0.37, 0, 0.63, 1; 0, 0, 1, 1"/>
</circle>
在这种方法中,您应该计算动画的总持续时间加上延迟并将其分配给 dur
,并计算持续时间的 keyTimes
值。对于我的示例,总持续时间为 12s
,时间 3s 1s 5s 1s 5s 映射到 keyTimes="0; 0.083; 0.5; 0.583; 1"
。
示例注释
calcMode="..."
和keySplines="..."
是可选的(它们指定 timing interpolation)- 初始动画延迟为3秒
- 动画(收缩和展开)每个需要 1 秒
- 开始到shrink/expand之前的延迟是5秒
以上两者都会产生以下结果: