使用动画时,clearInterval 不会停止触发的事件,或者第二个动画不会得到 运行

While working with animation, clearInterval does not stop event triggered, or second animation does not get run

我正在制作一个动画,有四个带有方向的按钮可以多次按下,还有 运行 按钮。当按下 运行 按钮时,它应该执行所有动作。

我有一个 catch 22 类型的问题,其中 ether 事件永远被触发并且动画永远不会停止或者它只 运行 一次。

我尝试了多种解决方案,现在选择了触发器,程序的工作方式是将移动添加到数组中,然后在 for 循环中触发,触发机制设置的触发器会在短时间内触发该方向。

下面的代码仅针对按钮 right 完成以重现问题只需单击它两次并按 运行 你就会明白我的意思,我还添加了指示问题的控制台调试, 和一个 Jsfiddle https://jsfiddle.net/0rxs9jpy/1/ 如果你想在它只触发一次的地方重现,检查这个 fiddle https://jsfiddle.net/0rxs9jpy/2/ 或取消注释行 //if (r) return;

var moves = [];
leftpx = 0;
downpx = 0;
uppx = 0;
rightpx = 0;
var up = function() {

  moves.push('up')

}

var down = function() {

  moves.push('down')

}

var left = function() {

  moves.push('left')

}

var right = function() {

  moves.push('right')

}
document.addEventListener("moveRight", function(e) {

});
document.addEventListener("stopRight", function(e) {
  console.log(e.detail);
  clearInterval(e.detail);

});

var Run = function() {


  for (var i = 0; i < moves.length; i++) {

    if (moves[i] == 'up') {
      document.getElementById('square').style.top = setInterval(myMove(), 3000);
    };
    if (moves[i] == 'left') {
      document.getElementById('square').style.left = myMove3()
    };
    if (moves[i] == 'down') {
      document.getElementById('square').style.top = myMove2()
    };
    if (moves[i] == 'right') {

      //if (r) return;
      var r = setInterval(function() {
        var event = new CustomEvent("moveRight", {
          "detail": "Example of an event"
        });
        document.dispatchEvent(event)
        var event1 = new CustomEvent("stopRight", {
          "detail": r
        });
        document.dispatchEvent(event1);
      }, 300);
    };
  }
  moves = [];
}

function myMove4(pos) {
  var elem = document.getElementById("square");
  var id = setInterval(frame, 5);
  var i = elem.style.left == '' ? 0 : parseInt(elem.style.left.replace('px', ''));
  pos = elem.style.left == '' ? pos : pos + i;

  console.log(i + ' ' + pos);

  function frame() {
    if (elem.style.left == pos + 'px') {
      clearInterval(id);
    } else {
      //  pos++;

      elem.style.left = (i++) + "px";


    }
  }
}
#square {
  width: 50px;
  height: 50px;
  background-color: blue;
  position: relative;
  animation: myfirst 5s linear 2s infinite alternate;
}
<input type='button' value='up' onclick='up()'></input>
<input type='button' value='down' onclick='down()'></input>
<input type='button' value='left' onclick='left()'></input>
<input type='button' value='right' onclick='right()'></input>
<input type='button' value='Run' onclick='Run()'></input>

<div id="square"></div>

<!--https://jsfiddle.net/0rxs9jpy-->

我正在寻找的是,如果我按两次右键然后 运行 它会执行两个动作然后停止。

一种方法是使用 javascript Promises

工作示例如下:

    <html>
    <head></head>
    <body>
    <input type = 'button' value = 'up' onclick = 'up()'></input>
    <input type = 'button' value = 'down' onclick = 'down()'></input>
    <input type = 'button' value = 'left' onclick = 'left()'></input>
    <input type = 'button' value = 'right' onclick = 'right()'></input>
    <input type = 'button' value = 'Run' onclick = 'Run()'></input>
    <br />
    <br />
    <br />
    <div id = "square"></div>
    <script>
          var moves = [];
          leftpx = 0;
          downpx = 0;
          uppx = 0;
          rightpx = 0;
          var up = function() {

              moves.push('up')

          }

          var down = function() {

              moves.push('down')

          }

          var left = function() {

              moves.push('left')

          }

          var right = function() {

              moves.push('right')

          }


          function setTimeoutPromise(ms) {
              return new Promise(function(resolve) {
                  setTimeout(resolve, ms);
              });
          }

          function foo(item, ms) {
              return function() {
                  return setTimeoutPromise(ms).then(function() {
                      if (item == 'right') {
                          myMove4(100)
                      };
                      if (item == 'down') {
                          myMove2(100)
                      };
                      if (item == 'left') {
                          myMove3(-100)
                      };
                      if (item == 'up') {
                          myMove(-100)
                      };
                  });
              };
          }


          function bar() {
              var chain = Promise.resolve();
              moves.forEach(function(el, i) {
                  chain = chain.then(foo(el,  600));
              });
              return chain;
          }

          bar().then(function() {});


          var Run = function() {
              bar();
              moves = [];
          }

          function myMove(pos) {
              var elem = document.getElementById("square");
              var id = setInterval(frame, 5);
              var i = elem.style.top == '' ? 0 : parseInt(elem.style.top.replace('px', ''));
              pos = elem.style.top == '' ? pos : pos + i;

              console.log(i + ' ' + pos);

              function frame() {
                  if (elem.style.top == pos + 'px') {
                      clearInterval(id);
                  } else {


                      elem.style.top = (i--) + "px";


                  }
              }
          }

          function myMove2(pos) {
              var elem = document.getElementById("square");
              var id = setInterval(frame, 5);
              var i = elem.style.top == '' ? 0 : parseInt(elem.style.top.replace('px', ''));
              pos = elem.style.top == '' ? pos : pos + i;

              console.log(i + ' ' + pos);

              function frame() {
                  if (elem.style.top == pos + 'px') {
                      clearInterval(id);
                  } else {
                      //  pos++;

                      elem.style.top = (i++) + "px";


                  }
              }
          }

          function myMove3(pos) {
              var elem = document.getElementById("square");
              var id = setInterval(frame, 5);
              var i = elem.style.left == '' ? 0 : parseInt(elem.style.left.replace('px', ''));
              pos = elem.style.left == '' ? pos : pos + i;

              console.log(i + ' ' + pos);

              function frame() {
                  if (elem.style.left == pos + 'px') {
                      clearInterval(id);
                  } else {
                      //  pos++;

                      elem.style.left = (i--) + "px";


                  }
              }
          }


          function myMove4(pos) {
              var elem = document.getElementById("square");
              var id = setInterval(frame, 5);
              var i = elem.style.left == '' ? 0 : parseInt(elem.style.left.replace('px', ''));
              pos = elem.style.left == '' ? pos : pos + i;

              console.log(i + ' ' + pos);

              function frame() {
                  if (elem.style.left == pos + 'px') {
                      clearInterval(id);
                  } else {
                      //  pos++;

                      elem.style.left = (i++) + "px";


                  }
              }
          }
    </script>
    <style>



    #square{
  
    width: 50px;
    height: 50px;
    background-color: blue;
    position: relative;
    animation: myfirst 5s linear 2s infinite alternate;
  
    }

    </style>


    </body>
    </html>