@keyframes 动画仅在第一次有效 文档和函数参考

问题描述

我在 select 中有 3 个值:rock、paper、scissor。

我第一次在选择中选择一个值(石头、纸或剪刀)时,onChange 事件触发,@keyframes 动画适用于所有 3 个值。

但是我第二次选择任何值时,动画不再起作用。 我不明白为什么。

代码是这样的: jsfiddle.net/9efvxph3/83/

body {
  background: radial-gradient(gold,goldenrod);
  font-family: monospace;
  text-align: center;
  font-size: 1.5rem;
}

@keyframes example {
  0% {
    transform: scale(1);
  }

  100% {
    transform: scale(1.3);
  }
}


img {
  padding: 10px;
  height: 100px;
  width: auto;
}

img:hover {
  transform: scale(1.4);
  transition: all 1s;
}
          <select id="choice" onchange="winner()">
            <option value="" disabled selected>choose</option>
            <option value="rock">rock</option>
            <option value="paper">paper</option>
            <option value="scissors">scissors</option>
          </select>

          <img src="https://img.icons8.com/windows/2x/hand-rock.png" class="user-choice">
          <img src="https://img.icons8.com/wired/2x/paper.png" class="user-choice">
          <img src="https://img.icons8.com/ios/2x/hand-scissors.png" class="user-choice">

          <h3 id="result"> </h3>

          <script>
            const type = ["paper","scissors","rock"];

            function winner() {
              var index = document.getElementById("choice").selectedindex;

              var userChooice = document.getElementById("choice").value;
              var PcChooice = type[Math.floor(Math.random() * type.length)];

              document.getElementsByClassName("user-choice").item(index - 1).style = "animation:example 0.5s alternate";

              if (PcChooice == userChooice) {

                document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You tied";

              } else {
                if ((userChooice == "rock") && (PcChooice == "scissors")) {
                  document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You win";
                } else if ((userChooice == "paper") && (PcChooice == "rock")) {
                  document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You win";
                } else if ((userChooice == "scissors") && (PcChooice == "paper")) {
                  document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You win";
                } else {
                  document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You loose";
                }
              }
              document.getElementById("choice").selectedindex = 0;
            };

          </script>

解决方法

根据您的代码,最好通过添加与动画结束相关的事件侦听器来结束您的函数,从元素的样式中删除动画。

在您的winner() 函数末尾添加以下代码:

document.getElementsByClassName("user-choice").item(index - 1).addEventListener("animationend",function(e) {
  e.target.style = "";
});

,

这是因为您在第一个选择中添加了一次内联动画,然后永远不会删除它,所以它永远不会再次被调用。无需重构所有内容的最简单方法是使用 animationend 事件在动画之后移除内联样式,甚至使用延迟比动画更长的 setTimeout() 之类的东西。

在添加动画后只需在某处添加以下内容即可:

document.getElementsByClassName("user-choice").item(index - 1).addEventListener("animationend",function(evt){
    evt.target.style = "";
});

或者,不太优雅:

setTimeout(function(){
    document.getElementsByClassName("user-choice").item(index - 1).style = "";
}.bind(index),510 );

这应该是您“解决问题”所需的全部内容,但查看可读性也可能有所帮助。

为了稍微清理一下 - 通常,如果您请求一个元素、节点列表(或任何真正的)不是 static property,您应该考虑将它存储在一个变量中。您可以将其存储为变量,并在最后调用一次函数(如 innerText),而不是在同一个 if/else 块中多次解析同一事物的 DOM。

如果您需要进行更改,这有助于避免在多个位置更新引用。

最后,您可能更适合将关键帧动画附加到类,并使用 classList 添加/删除类。

const type    = ["paper","scissors","rock"],result  = document.getElementById('result'),choice  = document.getElementById('choice'),choices = document.getElementsByClassName('user-choice');

function winner(){
    // Prevent changes while the game is "running"
    choice.disabled = true;

    var userChoice = choice.value,pcChoice   = type[Math.floor(Math.random() * type.length)],selected   = choices[choice.selectedIndex-1];
        status;
    
    if( pcChoice == userChoice ){
        status = 'tied';
    } else {
        if( userChoice == 'rock' && pcChoice == 'scissors' ){
            status = 'win';
        } else if( userChoice == 'paper' && pcChoice == 'rock' ){
            status = 'win';
        } else if( userChoice == 'scissors' && pcChoice == 'paper' ){
            status = 'win';
        } else {
            status = 'lose';
        }
    }

    selected.classList.add('animated');        
    result.innerText = userChoice + ' - ' + pcChoice + ': You ' + status;

    // After the animation,reset everything to its default state
    selected.addEventListener('animationend',function(evt){
        choice.disabled = false;
        choice.selectedIndex = 0;
        evt.target.classList.remove('animated');
    });
};
body {
  background: radial-gradient(gold,goldenrod);
  font-family: monospace;
  text-align: center;
  font-size: 1.5rem;
}

@keyframes example {
  0% { transform: scale(1); }
  100% { transform: scale(1.3); }
}


img {
  padding: 10px;
  height: 100px;
  width: auto;
}

img:hover {
  transform: scale(1.4);
  transition: all 1s;
}

img.animated {
  animation: example 0.5s alternate;
}
<select id="choice" onchange="winner()">
  <option value="" disabled selected>choose</option>
  <option value="rock">rock</option>
  <option value="paper">paper</option>
  <option value="scissors">scissors</option>
</select>

<img src="https://img.icons8.com/windows/2x/hand-rock.png" class="user-choice">
<img src="https://img.icons8.com/wired/2x/paper.png" class="user-choice">
<img src="https://img.icons8.com/ios/2x/hand-scissors.png" class="user-choice">

<h3 id="result"> </h3>


文档和函数参考

,

第一次在 select onchange 事件中选择值时会触发并添加动画样式。 (永久添加在dom中)

当您第二次选择任何值时 onchange 事件将触发但动画将不起作用因为它已经存在于 dom 中

添加 .animateonchange

CSS:

.animate {
  animation: example 0.5s alternate;
}

JS:

document.getElementsByClassName("user-choice").item(index - 1).classList.add('animate');

在添加 .animate 类之前,从所有 .user-choice 元素中删除 .animate 类。

var choicess = document.getElementsByClassName("user-choice");
[].forEach.call(choicess,function(el) {
  el.classList.remove('animate');
});

body {
  background: radial-gradient(gold,goldenrod);
  font-family: monospace;
  text-align: center;
  font-size: 1.5rem;
}

.animate {
  animation: example 0.5s alternate;
}

@keyframes example {
  0% {
    transform: scale(1);
  }
  100% {
    transform: scale(1.3);
  }
}

img {
  padding: 10px;
  height: 100px;
  width: auto;
}

img:hover {
  transform: scale(1.4);
  transition: all 1s;
}
<select id="choice" onchange="winner()">
  <option value="" disabled selected>choose</option>
  <option value="rock">rock</option>
  <option value="paper">paper</option>
  <option value="scissors">scissors</option>
</select>

<img src="https://img.icons8.com/windows/2x/hand-rock.png" class="user-choice">
<img src="https://img.icons8.com/wired/2x/paper.png" class="user-choice">
<img src="https://img.icons8.com/ios/2x/hand-scissors.png" class="user-choice">

<h3 id="result"> </h3>

<script>
  const type = ["paper","rock"];

  function winner() {
    var index = document.getElementById("choice").selectedIndex;

    var userChooice = document.getElementById("choice").value;
    var PcChooice = type[Math.floor(Math.random() * type.length)];

    var choicess = document.getElementsByClassName("user-choice");
    [].forEach.call(choicess,function(el) {
      el.classList.remove('animate');
    });

    document.getElementsByClassName("user-choice").item(index - 1).classList.add('animate');

    if (PcChooice == userChooice) {

      document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You tied";

    } else {
      if ((userChooice == "rock") && (PcChooice == "scissors")) {
        document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You win";
      } else if ((userChooice == "paper") && (PcChooice == "rock")) {
        document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You win";
      } else if ((userChooice == "scissors") && (PcChooice == "paper")) {
        document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You win";
      } else {
        document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You loose";
      }
    }
    document.getElementById("choice").selectedIndex = 0;
  };
</script>

,

您可以通过添加和删除类名而不是直接更新元素样式来简单地修复它。

修改下面一行

document.getElementsByClassName("user-choice").item(index - 1).style = "animation:example 0.5s alternate";

document.getElementsByClassName("user-choice").item(index - 1).classList.add('animate');
          
setTimeout(() => {
    document.getElementsByClassName("user-choice").item(index - 1).classList.remove('animate');
},1000)

其中 settimeout 延迟时间基于动画持续时间

body {
  background: radial-gradient(gold,goldenrod);
  font-family: monospace;
  text-align: center;
  font-size: 1.5rem;
}

@keyframes example {
  0% {
    transform: scale(1);
  }

  100% {
    transform: scale(1.3);
  }
}


img {
  padding: 10px;
  height: 100px;
  width: auto;
}

img:hover {
  transform: scale(1.4);
  transition: all 1s;
}

.animate {
  animation: example 0.5s alternate;
}
<select id="choice" onchange="winner()">
            <option value="" disabled selected>choose</option>
            <option value="rock">rock</option>
            <option value="paper">paper</option>
            <option value="scissors">scissors</option>
          </select>

          <img src="https://img.icons8.com/windows/2x/hand-rock.png" class="user-choice">
          <img src="https://img.icons8.com/wired/2x/paper.png" class="user-choice">
          <img src="https://img.icons8.com/ios/2x/hand-scissors.png" class="user-choice">

          <h3 id="result"> </h3>

          <script>
            const type = ["paper","rock"];

            function winner() {
              var index = document.getElementById("choice").selectedIndex;

              var userChooice = document.getElementById("choice").value;
              var PcChooice = type[Math.floor(Math.random() * type.length)];

              document.getElementsByClassName("user-choice").item(index - 1).classList.add('animate');
              
              setTimeout(() => {
                document.getElementsByClassName("user-choice").item(index - 1).classList.remove('animate');
              },1000)

              if (PcChooice == userChooice) {

                document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You tied";

              } else {
                if ((userChooice == "rock") && (PcChooice == "scissors")) {
                  document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You win";
                } else if ((userChooice == "paper") && (PcChooice == "rock")) {
                  document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You win";
                } else if ((userChooice == "scissors") && (PcChooice == "paper")) {
                  document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You win";
                } else {
                  document.getElementById("result").innerHTML = userChooice + " - " + PcChooice + ": You loose";
                }
              }
              document.getElementById("choice").selectedIndex = 0;
            };

          </script>

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...