dmar
dmar

Reputation: 21

Looping code with a delay

I am trying to create a simple drag race animation. The car image moves across the page upon the click of a button until each reaches a certain position. The code below works with individual clicks moving the car a random distance each click, but I want one click to repeat the movement in a loop. I have tried putting it in a while loop referencing the value of x, but it doesn't work. Any ideas.

<html>
<head>
  <meta charset="utf-8">
  <title>Race Car</title>
</head>
<body>
  <input type="button" id="move" value="race time" onClick="race()" />
  <div id="car" style="position: absolute; top: 150px"><img src="car.png"></div>
  <script src="https://code.jquery.com/jquery-2.1.0.js"></script>
  <script>
    //Get car position coordinates
    x = $("#car").offset().left;
    y = $("#car").offset().top;

    //Move car across screen by resetting car position coordinates
    var race = function() {
      var delay = 1000;

      setTimeout(function() {
        $("#car").css({
          left: x += Math.floor(Math.random() * 50),
          top: y
        });
        x = $("#car").offset().left;
      }, delay);
    };
  </script>
</body>

</html>

Upvotes: 2

Views: 96

Answers (4)

Nikola Mitic
Nikola Mitic

Reputation: 1492

You should use recursive setTimeout() not setInterval().

See why here --> https://develoger.com/settimeout-vs-setinterval-cff85142555b

This is how I like to approach this problem, with the function bellow you can pass number of iterations, time in between and actually callback.

  1. How many times? (you can set infinity)
  2. For how much to delay (in seconds)
  3. And to do WHAT?

See working example here --> https://jsfiddle.net/nmitic/bbr6y2a4/

const repeat = (numberOfIterations, timeBetweenItereation, stuffToRepeat) => {
  let iterationCounter = 0;
  const repeater = () => {
    setTimeout( () => {
       stuffToRepeat();
       iterationCounter++;
       if (iterationCounter >= numberOfIterations && numberOfIterations 
       !== Infinity)  {
        return;
       };
       if (iterationCounter >= numberOfIterations) {
          return;
       };
       repeater(); 
    }, 1000 * timeBetweenItereation);
  };
  repeater();
};

Upvotes: 0

Racil Hilan
Racil Hilan

Reputation: 25371

Why are you using variables instead of standard functions? Anyway, you can call your function recursively from within the setTimeout function until a condition is met. Try this:

<html>

<head>
  <meta charset="utf-8">
  <title>Race Car</title>
</head>

<body>
  <input type="button" id="move" value="race time" onClick="race()" />
  <div id="car" style="position: absolute; top: 150px"><img src="car.png"></div>
  <script src="https://code.jquery.com/jquery-2.1.0.js"></script>
  <script>
    //Get car position coordinates
    x = $("#car").offset().left;
    y = $("#car").offset().top;

    //Move car across screen by resetting car position coordinates
    function race() {
      var delay = 1000;

      setTimeout(function() {
        $("#car").css({
          left: x += Math.floor(Math.random() * 50),
          top: y
        });
        if (x < 200) //Specify where you want the movement to end.
          race();
      }, delay);
    }
  </script>
</body>

</html>

Upvotes: 2

Vignesh Raja
Vignesh Raja

Reputation: 8781

This will clear interval whenever you click the button and the race starts from the begining. Also no ned to set the top at every call, just left is enough. Happy racing!!!

x = $("#car").offset().left;
y = $("#car").offset().top;

//Move car across screen by resetting car position coordinates
var interval;
var race = function() {
  clearInterval(interval);
  var delay = 100, x=0;
  interval = setInterval(function() {
    $("#car").css({
      left: x += Math.floor(Math.random() * 50),
    });
    x = $("#car").offset().left;
  }, delay);
};
<input type="button" id="move" value="race time" onClick="race()" />
<div id="car" style="position: absolute; top: 150px"><img src="car.jpg"></div>

Upvotes: -1

MynockSpit
MynockSpit

Reputation: 449

You're looking for setInterval.

setTimeout runs your function once after x milliseconds.

setInterval runs your function every x milliseconds.

Be sure to store your interval in a variable you can access (var timer = setInterval(fn, ms)) and then clear it when you want to stop the interval (clearInterval(timer)).

Upvotes: 3

Related Questions