0

Ok, I have 8 divs and I need to have them animate in 1 at a time, meaning there is a delay between the 1st and 2nd, 2nd and 3rd, etc. At first I animate them all in, then depending on a dropdwin I will be animating only a few or couple of the divs in.

Regardless I need my animation to delay before running again with another div.

Here is my animation:

function panelIn(labDiv)
        {

            var neww = "100%";
  $(labDiv).delay(600).animate({
    width: neww
  }, 500);

        }

At first I tried setting a global variable and changing delay based on that, and that worked for 1st and 2nd divs but not for all subsequent:

function panelIn(labDiv)
        {
            if(wasFirst == true)
            {
                wasFirst = !wasFirst;
            var neww = "100%";
  $(labDiv).delay(600).animate({
    width: neww
  }, 500);
            }
            else {
                var neww = "100%";
  $(labDiv).delay(1200).animate({
    width: neww
  }, 500);
            }
        }

I will have to do something like this:

panelIn(div1);
panelIn(div2);
panelIn(div3);
panelIn(div4);

would like to avoid putting some wait function in between ALL of them. And that would be difficult also as Id need to delay the first by 600, the 2nd by 12000, the 3rd by 1800 and so on. I need it to be within the panelIn func and 1 set delay.

How can I make my divs animate in 1 at a time? Can this be done?

blue
  • 7,175
  • 16
  • 81
  • 179
  • Possible duplicate of [Chaining jQuery animations that affect different elements](http://stackoverflow.com/questions/4198091/chaining-jquery-animations-that-affect-different-elements) – devlin carnate Aug 21 '16 at 03:33
  • Check here to see how you can use ( animationend ) so you can start the next one and so on -- http://blog.teamtreehouse.com/using-jquery-to-detect-when-css3-animations-and-transitions-end -- but you will need to use CSS3 animations instead (.animate()) – Tasos Aug 21 '16 at 04:00

3 Answers3

2

There are 8 divs

<div class="animateContainer">
  <div class="animateThis">Item 1</div>
  <div class="animateThis">Item 2</div>
  <div class="animateThis">Item 3</div>
  <div class="animateThis">Item 4</div>
  <div class="animateThis">Item 5</div>
  <div class="animateThis">Item 6</div>
  <div class="animateThis">Item 7</div>
  <div class="animateThis">Item 8</div>
</div>

and you want to be able to trigger each of them but for them to be delayed. The first one is to be delayed by 600, 2nd by 1200, 3rd by 1800, etc.

var elems = $(".animateThis");

function panelIn(divNumber){
 var neww = "100%";
 $(elems[divNumber]).delay(600 * (divNumber+1)).animate({
    width: neww
  }, 500);

}

panelIn(0);
panelIn(1);
panelIn(2);
panelIn(3);
panelIn(4);
panelIn(5);
panelIn(6);
panelIn(7);

You can see this solution here https://jsfiddle.net/senordelaflor/h0z87r7f/2/

2

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()
Community
  • 1
  • 1
trusktr
  • 44,284
  • 53
  • 191
  • 263
1

From my comment using animationend and the HML and CSS code from the other Answer

CSS

.animate {
  width:100%;
    transition: width .5s linear;
}

Code

var i = 1; 
    function animate() { 

    var thisone = $(".animate" + i);
    thisone.addClass('animate');

    thisone.on('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend',   
        function(e) {
        i++;
        if (i < 9) {
        animate();
        }
      });
    };

    animate();

Demo

Tasos
  • 5,321
  • 1
  • 15
  • 26