简体   繁体   中英

How to get the setTimeout function to run and then stop using a loop

I am having trouble getting an image to stop moving while using setTimeout method. I have an image that moves a random amount across a page and I want it to stop once it reaches the other image. I tried putting the setTimeout in a while loop, but I cannot get it to work. Below is the code I have in an external javascript file, I invoke the moveCars() function in the HTML:

function moveCars() {
    RaceCar1();  
}

function RaceCar1() {
    var finish = document.getElementById('finish');
    var animate;
    var moveCar1 = Math.floor((Math.random() * 100) + 1);
    var car1 = document.getElementById('car1');
    car1.style.left = parseInt(car1.style.left) + moveCar1 + 'px'; 
    while(parseInt(car1.style.left) <= parseInt(finish.style.left)) {
    animate = setTimeout(RaceCar1, 500);
    }
}

Without the while loop, the image moves across the page forever. But with the while loop in there, the setTimeout only runs once.

*Note: I also tried just setting a value instead of using finish.style.left in the loop, but the image still continued to move.

You can refactor like this:

function moveCars() {
    RaceCar1();  
}

function RaceCar1() {
    var finish = document.getElementById('finish');
    var animate;
    var moveCar1 = Math.floor((Math.random() * 100) + 1);
    var car1 = document.getElementById('car1');
    car1.style.left = parseInt(car1.style.left) + moveCar1 + 'px'; 
    setTimeout(function(){
        if(parseInt(car1.style.left) <= parseInt(finish.style.left)) {
            RaceCar1();
        }
    }, 500);
}

An "if" statement should be enough. setTimeout calls the same function over and over again. Here's a quick example of that

var animate;
function RaceCar1() {
    var finish = document.getElementById('finish');
    var moveCar1 = Math.floor((Math.random() * 100) + 1);
    var car1 = document.getElementById('car1');
    car1.style.left = parseInt(car1.style.left) + moveCar1 + 'px';
    if (parseInt(car1.style.left) <= parseInt(finish.style.left)) {
        // OPrevent possible errors...
        if (animate) {
            clearTimeout(animate);
        }
        animate = setTimeout(function() { RaceCar1(); }, 500);
    }
}

I also set the animate timeout global so that you can cancel unncessary calls to "RaceCar1()".

Finally, I encapsulated "RaceCar1()" in an anonymous function so you get to access the previously declared variable if necessary (for scope sakes)

Hope that helped, this is obviously not tester.

Your code broke my browser, as it created an infinite loop of setTimeout calls due to your while clause. Change that to an if statement and it's fine. You simply wish to re-call your animation routine provided your logic still applies, so you only require an if for that. A while loop will continuously place stack calls to your animation loop repeatedly.

The following code works fine for me:

<script>
function moveCars() {
    RaceCar1();  
}

function RaceCar1() {
    var car1 = document.getElementById('car1');
    var finish = document.getElementById('finish');
    var animate;
    var moveCar1 = Math.floor((Math.random() * 100) + 1);
    car1.style.left = parseInt(car1.style.left) + moveCar1 + 'px';
    if (parseInt(car1.style.left) <= parseInt(finish.style.left)) {
        animate = setTimeout(RaceCar1, 500);
    }
}
</script>
<body onload="moveCars();">
    <p id="car1" style="position:absolute;left:0px;">Test</p>
    <p id="finish" style="position:absolute;left:600px;">Finish</p>
</body>

If you can use requestAnimationFrame , use that instead. Would be much better.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM