Although Pablo Martinez's answer shows you how to programmatically modify the delay, the answer is flawed: doing it that way means that we are timing out each animation (jQuery is probably using setTimeout
internally or similar), and due to the way the JavaScript engine works, the animations may overlap because timeouts are not executed exactly at the specified time, only approximately. If you try to fire events at the end or beginning of each animation, you may find that the events will not fire in the expected order (this is a fact, but I don't wish to make an example to prove it).
To guarantee that animations are fired consecutively, you should use promises returned by the .animate
method to run animations in sequence, and this will guarantee 100% that the animations will run consecutively and never overlap.
The following codes are untested, with techniques that are briefly explained in this answer (note, that answer also shows the wrong way using delays), and is effectively the same but without delay timing approximation:
const elems = $('.animateThis')
setTimeout(function() {
panelIn(0)
.then(() => panelIn(1)) // arrow function syntax
.then(() => panelIn(2))
.then(() => panelIn(3))
.then(() => panelIn(4))
.then(() => panelIn(5))
.then(() => panelIn(6))
.then(() => panelIn(7))
}, 500)
function panelIn(divNumber) {
const neww = '100%'
// return a promise (learn what promises are, they are useful!)
return $(elems[divNumber]).delay(100).animate({
width: neww
}, 500).promise()
}
If you're in an ES6 JavaScript environment that supports async functions, you can make the code cleaner:
async function sleep() {
return new Promise(function(resolve) {
return setTimeout(resolve, duration)
})
}
function panelIn(divNumber) {
const neww = '100%'
return $(elems[divNumber]).delay(100).animate({
width: neww
}, 500).promise()
}
async function animateDivs() {
const elems = $('.animateThis')
// Fire each animation sequentially. The `await` keyword makes the engine wait for the given promise to be resolved.
await sleep(500)
await panelIn(0)
await panelIn(1)
await panelIn(2)
await panelIn(3)
await panelIn(4)
await panelIn(5)
await panelIn(6)
await panelIn(7)
}
animateDivs()
Shortening it further, using arrow functions for sleep
and a for loop:
const sleep = duration => new Promise(r => setTimeout(r, duration))
function panelIn(divNumber) {
const neww = '100%'
return $(elems[divNumber]).delay(100).animate({
width: neww
}, 500).promise()
}
async function animateDivs() {
const elems = $('.animateThis')
await sleep(500)
for (let i=0; i<8; i++)
await panelIn(i)
}
animateDivs()
Bonus: if you want to do something after all the animations are complete, simply write another async function!
const sleep = duration => new Promise(r => setTimeout(r, duration))
function panelIn(divNumber) {
const neww = '100%'
return $(elems[divNumber]).delay(100).animate({
width: neww
}, 500).promise()
}
async function animateDivs() {
const elems = $('.animateThis')
await sleep(500)
for (let i=0; i<8; i++)
await panelIn(i)
}
async function animateDivsThenDoStuff() {
await animateDivs()
console.log('All animations complete!')
}
animateDivsThenDoStuff()