Search code examples
javascripttimerdom-eventseventtrigger

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


I am working on a animation there are four buttons with directions that can be pressed multiple times, and Run button. When Run buttons is pressed it should execute all the movements.

I have a catch 22 type of problem where ether events are fired forever and animation never stops or it only is being run once.

I tried multiple solutions and now settled on triggers, program works in a way where moves are being added to array and then fired in for loop, firing mechanism is setting triggers that would fire for that direction in short intervals.

Below code is done only for button right to reproduce the problem just click it twice and press run and you will see what I mean, I have also added console debugs that indicate the problem, and a Jsfiddle https://jsfiddle.net/0rxs9jpy/1/ If you want to reproduce where it only fires once check this fiddle https://jsfiddle.net/0rxs9jpy/2/ or uncomment line //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-->

What I am looking for is if I press the right button twice and then Run it does two movements and then stops.


Solution

  • One way to do this was to use javascript Promises

    Working example is below:

        <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>