【问题标题】:Can't launch same animation twice in a row无法连续两次启动相同的动画
【发布时间】:2019-04-17 17:06:56
【问题描述】:

我正面临 CSS 动画的“问题”。

我有一个 SVG,它由代表脸、眼睛、眉毛、手和笔记本的多个项目组成。

您可以想象我正在尝试为 SVG 的这些部分设置动画。 我有 3 个按钮代表 3 种类型的动画。这些是添加到需要动画的元素中的 CSS 关键帧。

我的问题:我无法连续两次运行相同的动画,而我可以一个一个地启动不同类型的动画。

我发现应该“重置”动画但似乎不起作用的“技巧”:

        currItem.style.animation = 'none';
        currItem.offsetHeight;
        currItem.style.animation = null;

CSS 动画对我来说有点新鲜,所以我可能会错过一些基本的“要求”。

PS:我知道我的代码有点难看,但我处于“沙盒”模式 atm 并且不想优化我的代码。

谢谢。

【问题讨论】:

  • 我的问题:我在帖子中看不到代码..?
  • 请阅读How to Askminimal reproducible example。与您的问题相关的代码一开始就直接属于您的问题,而不仅仅是转储在外部站点上。请相应地编辑您的问题。
  • 相信我,在发布之前我已经尝试了很多解决方案,包括您附加的帖子..
  • 在这里工作正常.. 我猜你发现了一个 JSFiddle 错误

标签: javascript css css-animations keyframe


【解决方案1】:

我不知道为什么您不能连续执行两次动画,但我找到了一种解决方法:将do_animation 包裹在setTimeout 中。这会强制 do_animation 在执行堆栈的末尾执行,所以我猜错误行为来自 CSS 引擎中未实时应用的样式或类似的东西。

另外,我认为这里的 Promise 完全没用,因为你所做的一切都是同步的。

编辑:我还优化了代码,缓存了所有元素并使用了 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>

【讨论】:

  • 保留原始代码并在这里尝试,它会正常工作......我猜JSFiddle有问题
  • 这种方式似乎工作得很好,但我想了解为什么超时正在修复它。我同意这里没有必要使用 promise,但我喜欢它。顺便感谢代码优化;)
  • 显然它也在 OP 的机器上本地执行此操作
  • 是的,我添加了解释为什么我相信会发生这种行为。
  • 感谢您的解释:)
猜你喜欢
  • 2019-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-18
  • 2020-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多