Jump to content
Search Community

getChildren() on Timeline with stagger

multivac test
Moderator Tag

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

Hello !

 

If a parent timeline contains staggers.

Calling parent.getChildren( false, false true ) will return a "timeline" for each stagger.

But these "timelines" will trigger an error if .getLabelsArray() is called on them

 

Is there a way to get children timelines, without the ones automatically created by stagger ?

 

Please look at the codepen.

 

Thanks

 

See the Pen YgLYYQ by multivac (@multivac) on CodePen

Link to comment
Share on other sites

Hi,

 

Yeah it is by design. A stagger method in a timeline returns a TimelineLite instance with a TweenLite instance for each element in the array passed to it, and since getLabelsArray is a method of the TimelineMax constructor you're getting undefined.

 

Also keep in mind that, besides the parameters of each stagger tween passed in the stagger method, you have no further control over those instances created by these methods. If you want to place a label where each stagger animation starts, you might want to take a longer road and use a loop in order to create each individual tween and place the desired label inside a TimelineMax instance.

 

The current code you posted, only gives you the possibility to add a label when the first stagger tween created by each stagger method starts.

 

Beyond the fact that:

 

console.log( children[i].getLabelsArray ); // -> undefined

 

There is not much I can infer from that code. Perhaps you can provide a few more details in order to get a better grasp of the roadblock you stumbled in your code.

 

Happy Tweening!!

  • Like 3
Link to comment
Share on other sites

Rodrigo, excellent job teaching stagger school!

 

—-

 

this is is an interesting scenario. The child timeline in this case is a TimelineLite and getLabelsArray() is a method of TimelineMax. 

 

Not sure what the solution is other than using a loop instead of a stagger. 

  • Like 1
Link to comment
Share on other sites

Thanks Buddy!!! I learned from the best ;)

 

The one option I can think, by looking at the GSAP code is extend TimelineLite prototype.

 

Since get labels array is quite simple:

 

https://github.com/greensock/GreenSock-JS/blob/master/src/uncompressed/TimelineMax.js#L431

 

And TimelineLite has a labels object just like it's Max counterpart:

 

https://github.com/greensock/GreenSock-JS/blob/master/src/uncompressed/TimelineLite.js#L25

 

This shouldn't return any problem (running some simple tests doesn't create an issue):

 

TimelineLite.prototype.getLabelsArray = TimelineMax.prototype.getLabelsArray;

 

Unless there is something I'm not totally aware of, in which case our beloved leader and tween-guide spirit @GreenSock could warn us against this.

 

Although this doesn't actually resolves anything as far as the original question, because still there is no way to introduce more than two labels in the main TimelineMax instance that holds the stagger methods. Unless Jack comes up with a new element in the API that allows dynamic labels in stagger methods using a base name for them and switching to TimelineMax. But IMHO it doesn't sound too useful, I'd go with the loop in order to add the animations to a TimelineMax instance.

Link to comment
Share on other sites

@multivac, there are actually several ways I can think of to address this but before I jump into anything I'd like to understand WHY you want to get to the labels. What exactly are you trying to accomplish? And how/where are you setting the labels in the first place? Are you trying to add a different label wherever any stagger animation is inserted? What format would the labels use? The more details you can provide, the better. 

Link to comment
Share on other sites

My software nests multiple timelines. I want the users to be able to reach a sub timeline by label name. My goal is to recursively scan all nested timelines and copy their labels to the parent at the correct time. 

 

I want to extract labels only from the nested timelines I've added. If I can sort out staggers it will be possible.

 

With Rodrigo answers it will be possible.

Link to comment
Share on other sites

Well as far as I know there is no direct way to get the type from an instance, but it could be something I'm not aware of, Jack could offer a final say in this.

 

What I can think of is the following. Single instances like TweenLite/Max don't have the .add() method while Timeline instances do, so that tells you if you're dealing with a timeline or single tween.

 

A TweenMax instance has the yoyo property so you can check that and finally a TimelineMax has the .getLabelsArray() method, as you already know :D, so a way to check would be this:

 

var checkInstance = function (instance) {
  if ( instance.add ) {
    // instance is a timeline
    if ( instance.getLabelsArray ) {
      // instance is TimelineMax
    } else {
      // instance is TimelineLite
    }
  } else {
    // instance is TweenLite or TweenMax
    if (instance.yoyo) {
      // instance is TweenMax
    } else {
      // instance is TweenLite
    }
  }
};

 

Happy Tweening!!

  • Like 1
Link to comment
Share on other sites

Yep, editing the prototype as @Rodrigo suggested should work.

 

The checking instance stuff could be done like this: 

 

function animationType(obj) {
    return (obj instanceof TimelineMax) ? "TimelineMax" : (obj instanceof TimelineLite) ? "TimelineLite" : (obj instanceof TweenMax) ? "TweenMax" : (obj instanceof TweenLite) ? "TweenLite" : "undefined";
}

 

Here's a quick function I whipped up that'll flatten the labels (find all labels in nested timelines and add them to the top level timeline that's passed into the function): 

function flattenLabels(tl) {
    var children = tl.getChildren(false, false, true),
        curTL, labels, p, i;
    for (i = 0; i < children.length; i++) {
        curTL = flattenLabels(children[i]);
        labels = curTL._labels; //undocumented
        for (p in labels) {
            tl.addLabel(p, curTL.startTime() + labels[p]);
        }
    }
    return tl;
}

 

Does that help? 

  • 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.
×
×
  • Create New...