0

To simplify this question I have created two divs: when you click on the orange box the blue box below it will move back and forth in a continuous loop. What I want to be able to do is:

  • Click the orange box to start and STOP the blue box loop
  • After starting and stopping, the blue box will stop and continue each time where it left off.

I've tried just about everything and can't get it to work. Any advice would be greatly appreciated.

var hoverSlideBox = document.getElementById("hover_slide_box");
var slidingBox = document.getElementById("sliding_box");

hoverSlideBox.onclick = function() {
  var pos = 0;
  var moveLeft = false;
  var stopAnimate = false;

  init();

  function init() {
    setInterval(boxRight, 5);
  }

  function boxRight() {
    if (!moveLeft) {
      pos++;
      slidingBox.style.left = pos + 'px';
    }
    if (pos == 500 || moveLeft) {
      moveLeft = true;
      boxLeft();
    }
  }

  function boxLeft() {
    if (moveLeft) {
      pos--;
      slidingBox.style.left = pos + 'px';
    }
    if (pos == 0 || !moveLeft) {
      moveLeft = false;
    }
  }

}
<div id="hover_slide_box" style="background-color: #ff931e; cursor: pointer; position: absolute; height: 100px; width: 100px;"></div>
<div id="sliding_box" style="top: 120px; background-color: #0071bc; cursor: pointer; position: absolute; height: 100px; width: 100px;"></div>
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Tarrant
  • 349
  • 1
  • 3
  • 9
  • Possible duplicate of [Implementing a pause and resume mechanism for javascript loop execution](http://stackoverflow.com/questions/26696717/implementing-a-pause-and-resume-mechanism-for-javascript-loop-execution) – Heretic Monkey Oct 20 '16 at 18:14

6 Answers6

1

To do this, you can use clearInterval to stop the movement. To make it resume when you click again, you just need to have your position variable in a permanent scope (I move it to the global scope for simplicity).

Changed code:

var pos = 0;
var moveLeft = false;
var stopAnimate = false;
var slideInterval;
hoverSlideBox.onclick = function() {
  init();

  function init() {
    if (slideInterval) {
      clearInterval(slideInterval);
      slideInterval = null;
    } else {
      slideInterval = setInterval(boxRight, 5);
    }
  }

Snippet:

var hoverSlideBox = document.getElementById("hover_slide_box");
var slidingBox = document.getElementById("sliding_box");

var pos = 0;
var moveLeft = false;
var stopAnimate = false;
var slideInterval;
hoverSlideBox.onclick = function() {
  init();

  function init() {
    if (slideInterval) {
      clearInterval(slideInterval);
      slideInterval = null;
    } else {
      slideInterval = setInterval(boxRight, 5);
    }
  }

  function boxRight() {
    if (!moveLeft) {
      pos++;
      slidingBox.style.left = pos + 'px';
    }
    if (pos == 500 || moveLeft) {
      moveLeft = true;
      boxLeft();
    }
  }

  function boxLeft() {
    if (moveLeft) {
      pos--;
      slidingBox.style.left = pos + 'px';
    }
    if (pos == 0 || !moveLeft) {
      moveLeft = false;
    }
  }

}
<div id="hover_slide_box" style="background-color: #ff931e; cursor: pointer; position: absolute; height: 100px; width: 100px;"></div>
<div id="sliding_box" style="top: 120px; background-color: #0071bc; cursor: pointer; position: absolute; height: 100px; width: 100px;"></div>
tcooc
  • 20,629
  • 3
  • 39
  • 57
  • Thanks of suggestion about creating a position variable. This was helpful too. I wish I could choose this answer as a co-answer. Thanks @tcooc! – Tarrant Oct 20 '16 at 18:43
1

You need to move some variables out of the onclick function so that they are not reset each time you click on the orange box. That, together with clearInterval, will give you a start/stop button.

var hoverSlideBox = document.getElementById("hover_slide_box");
var slidingBox = document.getElementById("sliding_box");
var running = false;
var intervalId;
var pos = 0;
var moveLeft = false;

hoverSlideBox.onclick = function() {

  init();

  function init() {
    if (!running) {
      intervalId = setInterval(boxRight, 5);
      running = true;
    } else {
      clearInterval(intervalId);
      running = false;
    }
  }

  function boxRight() {
    if (!moveLeft) {
      pos++;
      slidingBox.style.left = pos + 'px';
    }
    if (pos == 500 || moveLeft) {
      moveLeft = true;
      boxLeft();
    }
  }

  function boxLeft() {
    if (moveLeft) {
      pos--;
      slidingBox.style.left = pos + 'px';
    }
    if (pos == 0 || !moveLeft) {
      moveLeft = false;
    }
  }

}
<div id="hover_slide_box" style="background-color: #ff931e; cursor: pointer; position: absolute; height: 100px; width: 100px;"></div>
<div id="sliding_box" style="top: 120px; background-color: #0071bc; cursor: pointer; position: absolute; height: 100px; width: 100px;"></div>
Ryan H.
  • 7,374
  • 4
  • 39
  • 46
  • Of course! Moving the variables out of the function makes complete sense. There's one of those no-duh moments. Thank you very much, works perfectly. – Tarrant Oct 20 '16 at 18:40
0

setInterval returns interval id which you can use to cancel the interval using clearInterval

Damian
  • 2,752
  • 1
  • 29
  • 28
0

You could cancel the timer as the other answer says, or use requestAnimationFrame which is specifically designed for animations like these. See documentation here

This way we can simply check if stopAnimating is set before queueing up our next frame. You could do the same thing with setInterval if you wanted to, but requestAnimationFrame is probably better.

var hoverSlideBox = document.getElementById("hover_slide_box");
var slidingBox = document.getElementById("sliding_box");

hoverSlideBox.onclick = function() {
  var pos = 0;
  var moveLeft = false;
  var stopAnimate = false;

  init();

  function init() {
    animate();
  }
  
  function animate(){
    // stop animating without queueing up thenext frame
    if (stopAnimate) return;
    
    //queue up theh next frame.
    requestAnimationFrame(boxRight);
  }

  function boxRight() {
    if (!moveLeft) {
      pos++;
      slidingBox.style.left = pos + 'px';
    }
    if (pos == 500 || moveLeft) {
      moveLeft = true;
      boxLeft();
    }
    animate();
  }

  function boxLeft() {
    if (moveLeft) {
      pos--;
      slidingBox.style.left = pos + 'px';
    }
    if (pos == 0 || !moveLeft) {
      moveLeft = false;
    }
  }

}
<div id="hover_slide_box" style="background-color: #ff931e; cursor: pointer; position: absolute; height: 100px; width: 100px;"></div>
<div id="sliding_box" style="top: 120px; background-color: #0071bc; cursor: pointer; position: absolute; height: 100px; width: 100px;"></div>
Mobius
  • 2,871
  • 1
  • 19
  • 29
0

Your code doesn't clear the interval when box is clicked again. setInterval executes a function every number of given seconds. To stop it, you have use the function clearInterval, passing the timer id that the function setInterval returned.

Also, your code can be better organized. I've refactorized it base in the following advices:

  1. Don't use different functions for each direction. Your code have two different functions (moveLeft and moveRight) that are almost the same. Instead, use a simpler function that increments position given the current direction. Use a simple variable with the position increment, using -1 for left movement and +1 for right movement. If you have to modify the way the box moves you only have to change the moveBox function.

  2. Use a function to check if the box have reached the boundaries. In general is good to have small functions that do one simple thing. In your code, boundaries check is splited in the two movement functions. In the proposed code the check code is a separate function where you can modify boundaries easily in the future if needed, instead of changing them in different places of your code.

  3. Don't put all your logic in the click listener. Again, use simple functions that perform one simple task. The click listener should do a simple task, that's switching animation on and off. Initialization code should be in its onw function.

  4. Again, for simplicity, use a simple function as the function executed by setInterval. If not, you would have to change the function that is executed by the setInterval function: moveRight when box is moving to the right and moveLeft when the box is moving to the left. This makes the code more complex and hard to debug and mantain.

Those advices are not very useful with a small code like this, but its benefits are more visible when your code gets more complex.

var hoverSlideBox = document.getElementById("hover_slide_box");
var slidingBox = document.getElementById("sliding_box");

var pos = 0;
var direction = 1;
var animate = false;
var intervalHandler;



hoverSlideBox.onclick = function() {
  if (animate) {
    stop();
  }
  else {
    init();
  }    
}

function init() {
  animate = true;
  intervalHandler = setInterval(moveBox, 5);
}

function stop() {
  animate = false;
  clearInterval(intervalHandler);
}

function tic() {
  if (animate) {
    moveBox();
  }
}

function checkBoundaries() {
  if (pos == 500) {
    direction = -1;
  }
  else  if (pos == 0) {
    direction = 1;
  }
}

function moveBox() {
  pos += direction;
  slidingBox.style.left = pos + 'px';
  checkBoundaries();
}
<div id="hover_slide_box" style="background-color: #ff931e; cursor: pointer; position: absolute; height: 100px; width: 100px;"></div>
<div id="sliding_box" style="top: 120px; background-color: #0071bc; cursor: pointer; position: absolute; height: 100px; width: 100px;"></div>
sanzante
  • 844
  • 1
  • 11
  • 28
0

Try this snippet, it should work aswell

var hoverSlideBox = document.getElementById("hover_slide_box");
var slidingBox = document.getElementById("sliding_box");
var moveLeft = false;
var pos = 0;
var intervalID = null;

hoverSlideBox.onclick = function(){
    if (intervalID) {
        clearInterval(intervalID); 
        intervalID = null;
    } else {
        intervalID = setInterval(function () {
            pos += moveLeft ? -1 : 1;
            slidingBox.style.left = pos + 'px';
            moveLeft = pos >= 500 ? true : pos <= 0 ? false : moveLeft;
        }, 5);
    }
}
<div id="hover_slide_box" style="background-color: #ff931e; cursor: pointer; position: absolute; height: 100px; width: 100px;">
<div id="sliding_box" style="top: 120px; background-color: #0071bc; cursor: pointer; position: absolute; height: 100px; width: 100px;">
gamboa
  • 141
  • 3