无法连续两次启动相同的动画
Can't launch same animation twice in a row
我正面临 "problem" 动画 CSS。
我有一个 SVG,它由代表脸、眼睛、眉毛、手和笔记本的多个项目组成。
正如您想象的那样,我正在尝试为 SVG 的那些部分制作动画。
我有 3 个按钮,代表 3 种类型的动画。这些是 CSS 添加到需要动画的元素的关键帧。
我的问题:我无法连续运行同一动画两次,而我能够一个接一个地启动不同类型的动画。
我发现 "trick" 应该 "reset" 动画但似乎不起作用:
currItem.style.animation = 'none';
currItem.offsetHeight;
currItem.style.animation = null;
CSS 动画对我来说有点新,所以我可能会错过一些重要的东西 "requirements"。
PS:我知道我的代码有点难看,但我处于 "sandbox" 模式 atm,我没有尝试优化我的代码。
谢谢。
我不知道为什么你不能连续执行两次动画,但我找到了一个解决方法:将 do_animation
包裹在 setTimeout
中。这会强制 do_animation
在执行堆栈的末尾执行,所以我猜错误行为来自 CSS 引擎或类似的东西中没有实时应用的样式。
此外,我认为这里的 Promises 完全没有用,因为你所做的一切都是同步的。
编辑:我还优化了代码,缓存了所有元素并使用了 ES6。抱歉,忍不住这样做:)
var arr_items_to_animate = [
'left_eyebrow',
'right_eyebrow',
'face',
'hands_filled',
'right_eye',
'eyes',
'notebook',
'eyebrows',
'right_hand'
].map(id => document.getElementById(id)),
RightEye = document.getElementById('right_eye'),
Eyes = document.getElementById('eyes'),
Face = document.getElementById('face');
// reinit + start animation
const animate_bot = animationType => {
reInit();
setTimeout(() => {
do_animation(animationType);
})
}
// makes the animation
const do_animation = animationType => {
console.log("do_animation(" + animationType + ")");
switch (animationType) {
case 'wink':
RightEye.style.animation = "wink 0.3s ease-in 0s 1";
break;
case 'blink':
Eyes.style.animation = "blink 0.5s ease-in 0s 1";
break;
case 'nope':
Face.style.animation = "nope 1s ease-in 0s 1";
break;
}
}
// reinit all parts of svg
const reInit = () => {
// resets every part of svg
arr_items_to_animate.forEach(Elem => {
Elem.style.animation = 'none';
Elem.style.animation = null;
});
}
@keyframes wink {
0% {
transform: translate(0px, 0px)
}
30% {
transform: scale(1, 0.1) translate(0px, 300px)
}
70% {
transform: scale(1, 0.1) translate(0px, 300px)
}
100% {
transform: translate(0px, 0px)
}
}
@keyframes blink {
0% {
transform: translate(0px, 0px)
}
25% {
transform: scale(1, 0.1) translate(0px, 300px)
}
50% {
transform: translate(0px, 0px)
}
75% {
transform: scale(1, 0.1) translate(0px, 300px)
}
100% {
transform: translate(0px, 0px)
}
}
@keyframes nope {
0% {
transform: translate(0px, 0px)
}
40% {
transform: translate(0px, 0px)
}
50% {
transform: translate(2px, 0px)
}
60% {
transform: translate(-2px, 0px)
}
70% {
transform: translate(2px, 0px)
}
80% {
transform: translate(-2px, 0px)
}
90% {
transform: translate(2px, 0px)
}
100% {
transform: translate(0px, 0px)
}
}
<button onclick="animate_bot('nope')">Nope</button>
<button onclick="animate_bot('blink')">Blink</button>
<button onclick="animate_bot('wink')">Wink</button>
<svg id="myBot" viewBox="0 0 300 500">
<path id="head" d="M24,55A25,25 0 1,1 46,55" stroke="#1E569F" fill="none" stroke-width="9" />
<g id="face">
<g id="eyes">
<circle id="left_eye" cx="27" cy="32" r="3" stroke="none" fill="black" />
<circle id="right_eye" cx="42" cy="32" r="3" stroke="none" fill="black" />
</g>
<g id="eyebrows">
<path id="left_eyebrow" d="M22 27 Q 27 24 30 27" stroke="black" stroke-width="2" fill="none" />
<path id="right_eyebrow" d="M39 27 Q 42 24 47 27" stroke="black" stroke-width="2" fill="none" />
</g>
</g>
<g id="hands_filled"></g>
<g id="notebook">
<rect id="page" x="24" y="58" width="22" height="30" stroke="none" fill="#ee9220" />
<g id="text">
<line id="line1" x1="26" y1="63" x2="44" y2="63" stroke="white" />
<line id="line2" x1="26" y1="67" x2="44" y2="67" stroke="white" />
<line id="line3" x1="26" y1="71" x2="44" y2="71" stroke="white" />
</g>
</g>
<ellipse id="right_hand" cx="46" cy="76" rx="4" ry="5" stroke="none" fill="black" />
<ellipse id="left_hand" cx="24" cy="80" rx="4" ry="5" stroke="none" fill="black" />
Sorry, your browser does not support inline SVG.
</svg>
我正面临 "problem" 动画 CSS。
我有一个 SVG,它由代表脸、眼睛、眉毛、手和笔记本的多个项目组成。
正如您想象的那样,我正在尝试为 SVG 的那些部分制作动画。 我有 3 个按钮,代表 3 种类型的动画。这些是 CSS 添加到需要动画的元素的关键帧。
我的问题:我无法连续运行同一动画两次,而我能够一个接一个地启动不同类型的动画。
我发现 "trick" 应该 "reset" 动画但似乎不起作用:
currItem.style.animation = 'none';
currItem.offsetHeight;
currItem.style.animation = null;
CSS 动画对我来说有点新,所以我可能会错过一些重要的东西 "requirements"。
PS:我知道我的代码有点难看,但我处于 "sandbox" 模式 atm,我没有尝试优化我的代码。
谢谢。
我不知道为什么你不能连续执行两次动画,但我找到了一个解决方法:将 do_animation
包裹在 setTimeout
中。这会强制 do_animation
在执行堆栈的末尾执行,所以我猜错误行为来自 CSS 引擎或类似的东西中没有实时应用的样式。
此外,我认为这里的 Promises 完全没有用,因为你所做的一切都是同步的。
编辑:我还优化了代码,缓存了所有元素并使用了 ES6。抱歉,忍不住这样做:)
var arr_items_to_animate = [
'left_eyebrow',
'right_eyebrow',
'face',
'hands_filled',
'right_eye',
'eyes',
'notebook',
'eyebrows',
'right_hand'
].map(id => document.getElementById(id)),
RightEye = document.getElementById('right_eye'),
Eyes = document.getElementById('eyes'),
Face = document.getElementById('face');
// reinit + start animation
const animate_bot = animationType => {
reInit();
setTimeout(() => {
do_animation(animationType);
})
}
// makes the animation
const do_animation = animationType => {
console.log("do_animation(" + animationType + ")");
switch (animationType) {
case 'wink':
RightEye.style.animation = "wink 0.3s ease-in 0s 1";
break;
case 'blink':
Eyes.style.animation = "blink 0.5s ease-in 0s 1";
break;
case 'nope':
Face.style.animation = "nope 1s ease-in 0s 1";
break;
}
}
// reinit all parts of svg
const reInit = () => {
// resets every part of svg
arr_items_to_animate.forEach(Elem => {
Elem.style.animation = 'none';
Elem.style.animation = null;
});
}
@keyframes wink {
0% {
transform: translate(0px, 0px)
}
30% {
transform: scale(1, 0.1) translate(0px, 300px)
}
70% {
transform: scale(1, 0.1) translate(0px, 300px)
}
100% {
transform: translate(0px, 0px)
}
}
@keyframes blink {
0% {
transform: translate(0px, 0px)
}
25% {
transform: scale(1, 0.1) translate(0px, 300px)
}
50% {
transform: translate(0px, 0px)
}
75% {
transform: scale(1, 0.1) translate(0px, 300px)
}
100% {
transform: translate(0px, 0px)
}
}
@keyframes nope {
0% {
transform: translate(0px, 0px)
}
40% {
transform: translate(0px, 0px)
}
50% {
transform: translate(2px, 0px)
}
60% {
transform: translate(-2px, 0px)
}
70% {
transform: translate(2px, 0px)
}
80% {
transform: translate(-2px, 0px)
}
90% {
transform: translate(2px, 0px)
}
100% {
transform: translate(0px, 0px)
}
}
<button onclick="animate_bot('nope')">Nope</button>
<button onclick="animate_bot('blink')">Blink</button>
<button onclick="animate_bot('wink')">Wink</button>
<svg id="myBot" viewBox="0 0 300 500">
<path id="head" d="M24,55A25,25 0 1,1 46,55" stroke="#1E569F" fill="none" stroke-width="9" />
<g id="face">
<g id="eyes">
<circle id="left_eye" cx="27" cy="32" r="3" stroke="none" fill="black" />
<circle id="right_eye" cx="42" cy="32" r="3" stroke="none" fill="black" />
</g>
<g id="eyebrows">
<path id="left_eyebrow" d="M22 27 Q 27 24 30 27" stroke="black" stroke-width="2" fill="none" />
<path id="right_eyebrow" d="M39 27 Q 42 24 47 27" stroke="black" stroke-width="2" fill="none" />
</g>
</g>
<g id="hands_filled"></g>
<g id="notebook">
<rect id="page" x="24" y="58" width="22" height="30" stroke="none" fill="#ee9220" />
<g id="text">
<line id="line1" x1="26" y1="63" x2="44" y2="63" stroke="white" />
<line id="line2" x1="26" y1="67" x2="44" y2="67" stroke="white" />
<line id="line3" x1="26" y1="71" x2="44" y2="71" stroke="white" />
</g>
</g>
<ellipse id="right_hand" cx="46" cy="76" rx="4" ry="5" stroke="none" fill="black" />
<ellipse id="left_hand" cx="24" cy="80" rx="4" ry="5" stroke="none" fill="black" />
Sorry, your browser does not support inline SVG.
</svg>