Reputation: 3404
How specifically is it best to go about setting a timeout within a for loop? I have a square that upon click, the expected result is that it ticks down 1px every 500 ms. I'm attempting to do this by setting the CSS value of the top property to i
and wrapping in a timeout of 500 ms.
What is happening is it "hangs" on what looks like a first few pixels before launching straight to bottom.
What I have so far is below:
$("#rect").click(function() {
for (i = 0; i < 200; i++) {
(function(i){
setTimeout(function() {
$("#rect").css("top", i)
}, 500);
})(i);
}
});
$("#reset").click(function() {
$("#rect").css("top", "0");
});
#rect {
position: absolute;
top: 0;
width: 200px;
height: 50px;
background-color: #333;
}
#rect:hover {
cursor: pointer;
}
#reset {
float: right;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="rect"></div>
<button id="reset">reset</button>
Howcome stating the top property value of i
in a timeout within the loop doesn't work?
Upvotes: 0
Views: 159
Reputation: 12176
Your timing function is wrong change it to 500*i; if you want it to move every single iteration.
At present all your setTimeOuts fire at 500ms that's why it jumps
$("#rect").click(function() {
for (let i = 0; i < 200; i++) {
setTimeout(function() {
$("#rect").css("top", i);
}, 500*i);
}
});
$("#reset").click(function() {
$("#rect").css("top", "0");
});
But you can use lot of other solutions as mentioned in the other answers. Animate, slide up all are more robust.
Upvotes: 1
Reputation: 340
It looks like you're creating 200 timeouts that all run at the same time and each bump the element down a pixel giving the appearance that it shoots down.
What you're wanting is closer to this. Set an interval to run your function that moves the box every 500ms:
setInterval(moveBox, 500);
var boxMovedTimes = 0;
function moveBox() {
$('#rect').css('top', boxMovedTimes + "px");
boxMovedTimes += 1;
console.log('moved ' + boxMovedTimes)
}
Upvotes: 0
Reputation: 1210
I did not check your code, but uf you need to move a rectangle and you are already use jQuery, you may as well use jQuery sliding efects https://api.jquery.com/category/effects/sliding/
An example:
$( "#book" ).slideUp( "slow", function() {
// Animation complete.
});
Sometimes it is hard to create a simple effect like this, since it has to do with how the browser renders very fast changes on painting
Upvotes: 0
Reputation: 55
You setTimeout is in an anonymous function, so the loop calls the function and gets to the next iteration, setting the timeouts almost all at once.
Also, you might want to use setInterval to do that. It repeats the callback multiple times.
https://www.w3schools.com/jsref/met_win_setinterval.asp
Upvotes: 0