CSS 动画每 n 秒重复一次
CSS animation to repeat every nth second
我正在为一个 svg 元素制作动画,目前如下所示
.r1 {
transform-box: fill-box;
transform-origin: 50% 50%;
animation-name: simpleRotation,xRotation;
animation-delay: 0s, 2s;
animation-duration: 2s;
animation-iteration-count: 1, 1;
animation-timing-function: linear;
animation-direction: normal;
animation-fill-mode: forwards;
}
@keyframes simpleRotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
@keyframes xRotation {
from {
transform: rotateX(0deg);
}
to {
transform: rotateX(359deg);
}
}
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect class="r1" id="r1" x="10" y="10" width="10" height="10" stroke="black" stroke-width="0.25" fill="orange"></rect>
</svg>
是否可以将动画(使用 javascript)以某种方式排队,以便动画每 2 秒一个接一个地循环运行,例如 simpleRotation(0-2s);xRotation(2-4s);simpleRotation(4-6s);xRotation(6-8s);simpleRotation(8-10s);.....
在这种情况下,SVG animation 格式比 CSS 关键帧动画更易于使用 - 原则上。
SVG 动画可以定义与事件相关的动画开始时间 - 其中包括另一个动画的结束时间。这样您就可以将动画链接在一起,并且可以定义循环:
<animate id="first" begin="0s;second.end" ... />
<animate id="second" begin="first.end" ... />
第一个动画开始于0s
,另外由第二个动画结束触发,第二个动画由第一个动画结束触发。
您的用例的问题是您想要为 3D 变换函数设置动画。 SVG transform
在语法上不同于 CSS transform
,并且只支持 2D 转换。所以下面的例子最多只能模拟一下效果,很多细节还得另写。
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect id="r1" x="-5" y="-5" transform="translate(15 15)"
width="10" height="10" stroke="black" stroke-width="0.25" fill="orange">
<animateTransform id="simpleRotation" attributeName="transform" type="rotate"
additive="sum" begin="0s;xRotation.end" dur="2s"
from="0" to="360" />
<animateTransform id="xRotation" attributeName="transform" type="scale"
additive="sum" begin="simpleRotation.end" dur="2s"
values="1 1;1 -1;1 1" keyTimes="0;0.5;1"
calcMode="spline" keySplines=".375 0 .375 1;.375 0 .375 1" />
</rect>
</svg>
- 动画对象的中心最初放置在
0,0
以简化以下变换。每个 <animateTransform>
都有一个 additive="sum"
属性,因此它是 post-multiplied 到动画对象上的静态 translate()
属性。
- 为了模拟
xRotate()
,使用 scale
变换将 y 轴从 1 缩放到 -1 并返回。此外,还定义了样条插值以提供平滑“旋转”的印象。请注意,此模拟仅在没有 perspective
. 的情况下有效
的替代方法可能是使用网络动画 API
关键帧动画可以翻译成这样的动画对象
let ani1 = animEl.animate(
[{
transform: "rotate(0deg)"
}, {
transform: "rotate(359deg)"
}], {
delay: 500,
duration: 1000,
iterations: 1
}
);
另请参阅:MDN: Using the Web Animations API
例子
let animEl = document.querySelector(".rect1");
let ani1 = animEl.animate(
[{
transform: "rotate(0deg)"
}, {
transform: "rotate(359deg)"
}], {
delay: 500,
duration: 1000,
iterations: 1
}
);
let ani2 = animEl.animate(
[{
transform: "rotateX(0deg)"
}, {
transform: "rotateX(359deg)"
}], {
delay: 500,
duration: 1000,
iterations: 1,
}
);
// pause 2. animation
ani2.pause();
// chain animations
ani1.onfinish = function() {
ani2.play();
};
ani2.onfinish = function() {
ani1.play();
};
svg {
border: 1px solid #ccc;
display: block;
width: 10em
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect class="rect1" id="r1" x="25" y="25" width="50" height="50" stroke="black" stroke-width="0.25" fill="orange" transform-origin="50 50" ></rect>
</svg>
我们通过
暂停第二个开始动画
ani2.pause();
并添加一个 eventListener 以在第一个动画完成后启动第二个动画。
ani1.onfinish = function() {
ani2.play();
};
编辑你也可以使用premises as described by Dan Wilson
不要错过 svg 的 SMIL 动画的强大功能
特别是当涉及到 svg 相关动画时,他们仍然提供许多在 css 动画中不可用的花里胡哨的东西,例如
连续动画:
<动画[...] begin="firstAnimation.end" />
通过 begin
属性 启动连续动画(无需计算之前的持续时间)的能力真是太棒了——这个优雅的概念应该被应用到相应的 css 动画中方法。
- 沿路径移动元素
- 自包含动画——比如加载微调器
... svg 获胜!
犬:
SMIL animations tend to have more solid browser support than Web Animations API
虽然,由于 Internet Explorer 的感激退休,它可以忽略不计。
我正在为一个 svg 元素制作动画,目前如下所示
.r1 {
transform-box: fill-box;
transform-origin: 50% 50%;
animation-name: simpleRotation,xRotation;
animation-delay: 0s, 2s;
animation-duration: 2s;
animation-iteration-count: 1, 1;
animation-timing-function: linear;
animation-direction: normal;
animation-fill-mode: forwards;
}
@keyframes simpleRotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
@keyframes xRotation {
from {
transform: rotateX(0deg);
}
to {
transform: rotateX(359deg);
}
}
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect class="r1" id="r1" x="10" y="10" width="10" height="10" stroke="black" stroke-width="0.25" fill="orange"></rect>
</svg>
是否可以将动画(使用 javascript)以某种方式排队,以便动画每 2 秒一个接一个地循环运行,例如 simpleRotation(0-2s);xRotation(2-4s);simpleRotation(4-6s);xRotation(6-8s);simpleRotation(8-10s);.....
在这种情况下,SVG animation 格式比 CSS 关键帧动画更易于使用 - 原则上。
SVG 动画可以定义与事件相关的动画开始时间 - 其中包括另一个动画的结束时间。这样您就可以将动画链接在一起,并且可以定义循环:
<animate id="first" begin="0s;second.end" ... />
<animate id="second" begin="first.end" ... />
第一个动画开始于0s
,另外由第二个动画结束触发,第二个动画由第一个动画结束触发。
您的用例的问题是您想要为 3D 变换函数设置动画。 SVG transform
在语法上不同于 CSS transform
,并且只支持 2D 转换。所以下面的例子最多只能模拟一下效果,很多细节还得另写。
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect id="r1" x="-5" y="-5" transform="translate(15 15)"
width="10" height="10" stroke="black" stroke-width="0.25" fill="orange">
<animateTransform id="simpleRotation" attributeName="transform" type="rotate"
additive="sum" begin="0s;xRotation.end" dur="2s"
from="0" to="360" />
<animateTransform id="xRotation" attributeName="transform" type="scale"
additive="sum" begin="simpleRotation.end" dur="2s"
values="1 1;1 -1;1 1" keyTimes="0;0.5;1"
calcMode="spline" keySplines=".375 0 .375 1;.375 0 .375 1" />
</rect>
</svg>
- 动画对象的中心最初放置在
0,0
以简化以下变换。每个<animateTransform>
都有一个additive="sum"
属性,因此它是 post-multiplied 到动画对象上的静态translate()
属性。 - 为了模拟
xRotate()
,使用scale
变换将 y 轴从 1 缩放到 -1 并返回。此外,还定义了样条插值以提供平滑“旋转”的印象。请注意,此模拟仅在没有perspective
. 的情况下有效
关键帧动画可以翻译成这样的动画对象
let ani1 = animEl.animate(
[{
transform: "rotate(0deg)"
}, {
transform: "rotate(359deg)"
}], {
delay: 500,
duration: 1000,
iterations: 1
}
);
另请参阅:MDN: Using the Web Animations API
例子
let animEl = document.querySelector(".rect1");
let ani1 = animEl.animate(
[{
transform: "rotate(0deg)"
}, {
transform: "rotate(359deg)"
}], {
delay: 500,
duration: 1000,
iterations: 1
}
);
let ani2 = animEl.animate(
[{
transform: "rotateX(0deg)"
}, {
transform: "rotateX(359deg)"
}], {
delay: 500,
duration: 1000,
iterations: 1,
}
);
// pause 2. animation
ani2.pause();
// chain animations
ani1.onfinish = function() {
ani2.play();
};
ani2.onfinish = function() {
ani1.play();
};
svg {
border: 1px solid #ccc;
display: block;
width: 10em
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect class="rect1" id="r1" x="25" y="25" width="50" height="50" stroke="black" stroke-width="0.25" fill="orange" transform-origin="50 50" ></rect>
</svg>
我们通过
暂停第二个开始动画 ani2.pause();
并添加一个 eventListener 以在第一个动画完成后启动第二个动画。
ani1.onfinish = function() {
ani2.play();
};
编辑你也可以使用premises as described by Dan Wilson
不要错过 svg 的 SMIL 动画的强大功能
特别是当涉及到 svg 相关动画时,他们仍然提供许多在 css 动画中不可用的花里胡哨的东西,例如
连续动画:
<动画[...] begin="firstAnimation.end" />
通过 begin
属性 启动连续动画(无需计算之前的持续时间)的能力真是太棒了——这个优雅的概念应该被应用到相应的 css 动画中方法。
- 沿路径移动元素
- 自包含动画——比如加载微调器 ... svg 获胜!
犬:
SMIL animations tend to have more solid browser support than Web Animations API
虽然,由于 Internet Explorer 的感激退休,它可以忽略不计。