Schira
Schira

Reputation: 25

Looping several setTimeout() functions?

I have succesed to make my animation where i'm changing the size of the div´s with a setTimeout. The problem is, that i can't find a way for them to loop, i´ve tried to call to start() function within the function itself, but after the first execution, the animation gets really messy. Can someone help me with making the whole sequence loop without any trouble?

$(document).ready(function () {
    alert('Sådan!');
});


function div1ind() {
    $(function () {
        $('#div1').css({
            'z-index': 2
        })
    });

    $(function () {
        $('#div1').animate({
            height: '1080px',
            width: '1918px',
            top: '0px',
            left: '0px'
        }, 500);
    });

}

function div1ud() {

    $(function () {
        $('#div1').animate({
            height: '540px',
            width: '959px',
            top: '0px',
            left: '0px'
        }, 500);

    });



    $(function () {
        $('#div1').css({
            'z-index': 1
        })
    });
}

function div2ind() {

    $(function () {
        $('#div2').css({
            'z-index': 2
        })
    });

    $(function () {
        $('#div2').animate({
            height: '1080px',
            width: '1918px',
            top: '0px',
            left: '0px'
        }, 500);
    });


}



function div2ud() {

    $(function () {
        $('#div2').animate({
            height: '540px',
            width: '959px',
            top: '0px',
            left: '959px'
        }, 500);

    });


    $(function () {
        $('#div2').css({
            'z-index': 1
        })
    });
}

function div3ind() {

    $(function () {
        $('#div3').css({
            'z-index': 2
        })
    });

    $(function () {
        $('#div3').animate({
            height: '1080px',
            width: '1918px',
            top: '0px',
            left: '0px'
        }, 500);
    });

}

function div3ud() {

    $(function () {
        $('#div3').animate({
            height: '540px',
            width: '959px',
            top: '540px',
            left: '0px'
        }, 500);

    });

    $(function () {
        $('#div3').css({
            'z-index': 1
        })
    });
}

function div4ind() {

    $(function () {
        $('#div4').css({
            'z-index': 2
        })
    });

    $(function () {
        $('#div4').animate({
            height: '1080px',
            width: '1918px',
            top: '0px',
            left: '0px'
        }, 500);
    });
}

function div4ud() {

    $(function () {
        $('#div4').animate({
            height: '540px',
            width: '959px',
            top: '540px',
            left: '959px'
        }, 500);

    });


    $(function () {
        $('#div4').css({
            'z-index': 1
        })
    });
}

function start() {

    $(function () {
        setTimeout('div1ind()', 2000);
        setTimeout('div1ud()', 4000);
        setTimeout('div2ind()', 6000);
        setTimeout('div2ud()', 8000);
        setTimeout('div3ind()', 10000);
        setTimeout('div3ud()', 12000);
        setTimeout('div4ind()', 14000);
        setTimeout('div4ud()', 16000);
    });
}

start();

Upvotes: 2

Views: 148

Answers (2)

Steven Moseley
Steven Moseley

Reputation: 16345

This is a better case for setInterval, so as to prevent race conditions with multiple timeout instances.

The added benefit to a solution like this is that you can easily add or remove function calls to your list without reprogramming and double-checking all the timeouts.

What I'm doing here is creating an array that maps to your other functions, and then setting an interval that will trigger every 2 seconds. The interval increments the value of i, and calls the function that is the modulus of i % x (where x is the number of functions in your list).

(Edit: tweaked the code to be neater. Edit 2: wrapped in an anonymous function to prevent calling the same index.)

var i = 0;
var function_map = [div1ind, div1ud, div2ind, div2ud, div3ind, div3ud, div4in, div4ud];    
window.setInterval(function() {
    function_map[i++ % function_map.length]()
}, 2000);

EDIT: Per your comment below, if you want them to have different delays, you could do this (add the timeout into the function map and build a recursive timeout chain):

var i = 0;
var function_map = [
    [1000,div1ind], 
    [2000,div1ud], 
    [3000,div2ind], 
    [2000,div2ud], 
    [5000,div3ind], 
    [3000,div3ud], 
    [4000,div4in], 
    [2000,div4ud]
];
function start() {    
    var func = function_map[i++ % function_map.length];
    window.setTimeout(function() {
        func[1]();
        start();
    }, func[0]);
}
start();

Upvotes: 1

Guffa
Guffa

Reputation: 700630

Your setTimeout calls makes the functions start at different times, so make another that makes the start function start again:

function start() {
  setTimeout(div1ind, 2000);
  setTimeout(div1ud, 4000);
  setTimeout(div2ind, 6000);
  setTimeout(div2ud, 8000);
  setTimeout(div3ind, 10000);
  setTimeout(div3ud, 12000);
  setTimeout(div4ind, 14000);
  setTimeout(div4ud, 16000);
  setTimeout(start, 18000);
}

Don't use $(function(){ ... }) everywhere, that is a shorthand for $.ready(function(){ ... }), i.e. it would bind the ready event. However, if you do that after the ready event has occured, jQuery will just call the callback immediately, so it's just useless code.

Bind the ready event once to start the start function, and remove that extra wrappers from all your functions. Instead of:

start();

use this to use the start function as callback for the ready event handler:

$(start);

or the equivalent:

$(document).ready(start);

Upvotes: 1

Related Questions