Reputation: 21
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
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.
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
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
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
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