Jump to content
GreenSock

dada78

Animating array of items in a staggered way

Go to solution Solved by Carl,

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hi guys,

I am playing around with this codepen animation and have the following questions:

 

1_ Currently the items are animating in staggered, even though I didn't assign a "staggerTo", why is this? ( I do want them to animate in this way, but I don't understand why this happens naturally). 

 

2_ How would I go about it if I wish to control the stagger time of the array items coming in?

 

Thanks very much!

See the Pen fd4f35272d48df628148f98c4a9e5459 by dada78 (@dada78) on CodePen

Link to comment
Share on other sites

Howdy!

 

The staggered effect is coming from the randomized position parameter shown here:

L5ueBsg.png

 

next, i think structurally you meant to use the technique of using an add() to call a function that returns a timeline. So I would suggest these modifications:

 

Vi6R94a.png

 

 

If you want to stagger them in with random start times, what you can do is use the cycle feature to randomize the delay of each tween created by staggerTo() like:

function spotsIn(){
  
  var child = new TimelineLite();
      child.staggerTo(spotsAll, 0.5, {autoAlpha:1, ease: Back.easeOut.config(1.8), 
             cycle:{
               delay:function() {
                 return Math.random() * 1;
               }
             }
        }); 
  //return the timeline
  return child;
  }

 

http://codepen.io/GreenSock/pen/JXzBNw?editors=0010

 

If you haven't used cycle before check out the video here: http://greensock.com/gsap-1-18-0

  • Like 3
Link to comment
Share on other sites

Thanks so much Carl for the thorough explanation!

But I am still not understanding how I would be able to set the delay for the randomly appearing li items?

 

I thought that Math.random() would only randomize the order the li elements would animate in (ie. 2,6,1,.. versus 1,2,3,..) and not also have an impact on the time delay each item would animate in. For example, I would like to set the delay between items to be a set time like 0.8s.

 

What I wanted to achieve is basically have the li items animate in in random order, how they are doing now, but have control over the delay in between each li item appearing.

  • Like 1
Link to comment
Share on other sites

  • Solution

ah, ok, I didn't know that you needed random order at consistent intervals. That's a bit different.

 

To do that you need to actually shuffle the array that you are passing into the stagger.

I found a nice shuffle() method on StackOverflow.

What I didn't realize initially though is that when you do 

 

document.querySelectorAll("#spots li");

 

it gets a NodeList which looks a lot like an Array but it isn't.

 

https://developer.mozilla.org/en-US/docs/Web/API/NodeList

 

This caused the array shuffle() method not to work. So I had to add an additional step of looping through the NodeList and putting all those nodes in a proper Array. I have a hunch someone around here may have a more elegant solution, but this should work:

 

var spotsNodeList = document.querySelectorAll("#spots li");
var spotsArray = [];


//take each node from spotsNodeList and put it into spotsArray
for (var i = 0; i < spotsNodeList.length; ++i) {
  spotsArray.push(spotsNodeList[i]);  
}


spotsArray = shuffle(spotsArray);


var tl = new TimelineMax(); 
tl
  .set(spotsArray, {autoAlpha:0})
  //call function that returns a timeline
  .add(spotsIn());


function spotsIn(){
  
  var child = new TimelineLite();
      child.staggerTo(spotsArray, 0.5, {autoAlpha:1, ease: Back.easeOut.config(1.8)}, 1); 
  //return the timeline
  return child;
  }




//the magic sauce
function shuffle(array) {
    for (var i = array.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    return array;
}

 

 

 

http://codepen.io/GreenSock/pen/bpZmzN

  • Like 2
Link to comment
Share on other sites

Nice job. By the way a quick way to convert a NodeList into an Array is:

var list = document.querySelectorAll(".whatever"); //NodeList
var ar = [].slice.call(list); //BOOM, returns an array. 
  • Like 5
Link to comment
Share on other sites

Thanks so much Carl and Jack! I ALWAYS learn something new here. It's fantastic and your memberships are truly worth all this information!

 

Here is a codepen that also incorporates Jack's simplified method of creating an array from a nodelist: 

 

See the Pen 7a668e743c2d0c958ca09ca6685096a6?editors=1010 by dada78 (@dada78) on CodePen

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×