Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Carl-Philippe

Stagger from the last element

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!

 

I would like to animate a stagger tween from the last element. For instance, start a splittext animation from the last word.

I can't use tweenmax.reverse() because my stagger animation is a part of a timeline. I tried different combination but it did not work as planed.

 

Here a sample of the timeline.


var tl = new TimelineMax();

tl.insert(TweenMax.to( arrowP,0.6,{css:{left:0, opacity:1}, ease:ease1}));
tl.insert(TweenMax.to( arrowP,0.2,{css:{left:40, opacity:0}, delay:0.6, ease:ease1}));
tl.insert(TweenMax.from( arrowSpan,0.6,{css:{left:-200}, delay:0.2, ease:ease1}));

tl.insert(TweenMax.staggerFrom(mySplitText.chars, 0.2, {autoAlpha:0, x:-40, delay:0.2, ease:ease1}, 0.02));

So, do you have an idea of how I could proceed if it is possible ?

 

Thank you so much for your help!

Link to post
Share on other sites

Hi and welcome to the GreenSock forums.

 

Using a negative stagger value will make the animation start with the last element in the targets array:

var mySplitText = new SplitText("#quote", {type:"chars,words"}),
    tl = new TimelineLite();

//negative stagger value (-0.2)
tl.staggerFrom(mySplitText.chars, 0.5, {opacity:0, y:50}, -0.2)

http://codepen.io/anon/pen/vDGAq

  • Like 9
Link to post
Share on other sites

Hi and welcome to the Greensock forums.

 

I know two ways.

 

First you could revert the array order using JS and the use the staggerFrom() instance.

 

Two, create an independent timeline with the stagger and play it from the end using reverse(0):

var tl = new TimelineMax(),
    childTl = new TImelineMax();

childTl.staggerFrom(mySplitText.chars, 0.2, {vars});

tl.call(playChild);

function playChild()
{
  childTl.reverse(0);
}

Rodrigo.

  • Like 2
Link to post
Share on other sites

Great trick Carl.. i didn't know that a negative stagger value would make the animation start with the last element in the target array.. Nice :)

Link to post
Share on other sites

The negative stagger value technically works here, but I'd advise caution with that because it actually makes the startTimes go backwards, so for example, if you've got 10 elements in the array and you put the staggerTo() at the beginning of the timeline and the stagger is -0.1, the last tween would actually be positioned to start at a time of -1 which is before the timeline's start. Luckily there's code in place that senses that condition and literally picks up and moves all the tween forward because it knows that nothing is supposed to start before a time of 0. 

 

That's why it works here, but let's say you had built a timeline that already had 10 seconds of animations in it, and you append a staggerTo() to the end with a negative stagger value - you'd end up getting an overlap. If we took the example above (10 elements, -0.1 stagger), the last element in the array would start animating 1 second before the end of that timeline. Of course you can use that to your advantage. And it's not a bug or anything - you're asking it to stagger the start times by a negative number after all. 

 

The only other situation I can think of that might surprise you is if you've got a timeline that already has a bunch of tweens in it, and you put a staggerTo() at the very beginning of the timeline, and use a negative stagger - since that produces tweens with negative startTimes, the timeline would have to pick all the tweens up (including the existing ones in the timeline so that things remain synchronized properly) and move them forward, thus the startTimes of the old stuff would be affected. 

 

In my opinion, if you want to reverse the order in the array, just do this and use a positive stagger:

var reversedChars = mySplitText.chars.slice(0);
reversedChars.reverse();
tl.staggerFrom(reversedChars, 0.5, {opacity:0, y:50}, 0.2);
  • Like 5
Link to post
Share on other sites

We may actually alter the way the stagger methods work in a future version of GSAP so that when a negative stagger is used, it simply reverses the array internally, thus avoiding the "back-shift" timing thing. If anyone wants to chime in and vote for what they think is the most "intuitive" behavior, please do. 

  • Like 3
Link to post
Share on other sites

IMHO reverting the array is the best way to go, getting too creative with timing may cause some problems in scenarios with lots of nested animations, specially if you nest more than one timeline inside a parent one, you need to manually add a delay or dummy tween in the previous instance in order to correct the sequence timing. If the timeline is dynamically populated? you need to create some code to calculate how much time you need to offset the previous element, then apply it, ughh.. no thanks.

 

One of the great things of GSAP is the timing precision (main reason why at some point you forget about setTimeout and setInterval in order to keep everything in sync using delayedCall), no need to change that, at least that's how I see it.

 

I'm for reverting the array.

 

Happy Tweening!!

Link to post
Share on other sites

Jack you said everything ! And your answer helps me to resolve quickly my issue.
Thank you everyone for your help.

Link to post
Share on other sites
  • 4 years later...
On 1/10/2014 at 8:17 PM, GreenSock said:

The negative stagger value technically works here, but I'd advise caution with that because it actually makes the startTimes go backwards, so for example, if you've got 10 elements in the array and you put the staggerTo() at the beginning of the timeline and the stagger is -0.1, the last tween would actually be positioned to start at a time of -1 which is before the timeline's start. Luckily there's code in place that senses that condition and literally picks up and moves all the tween forward because it knows that nothing is supposed to start before a time of 0. 

 

That's why it works here, but let's say you had built a timeline that already had 10 seconds of animations in it, and you append a staggerTo() to the end with a negative stagger value - you'd end up getting an overlap. If we took the example above (10 elements, -0.1 stagger), the last element in the array would start animating 1 second before the end of that timeline. Of course you can use that to your advantage. And it's not a bug or anything - you're asking it to stagger the start times by a negative number after all. 

 

The only other situation I can think of that might surprise you is if you've got a timeline that already has a bunch of tweens in it, and you put a staggerTo() at the very beginning of the timeline, and use a negative stagger - since that produces tweens with negative startTimes, the timeline would have to pick all the tweens up (including the existing ones in the timeline so that things remain synchronized properly) and move them forward, thus the startTimes of the old stuff would be affected. 

 

In my opinion, if you want to reverse the order in the array, just do this and use a positive stagger:


var reversedChars = mySplitText.chars.slice(0);
reversedChars.reverse();
tl.staggerFrom(reversedChars, 0.5, {opacity:0, y:50}, 0.2);


Quick question: It is late 2018 - is this still valid? Or did GSAP come up with a different solution, as @GreenSock vaguely points out?

  • Like 1
Link to post
Share on other sites

Hi @Robert Wildling :)

 

I believe the negative value is the way to go. Similar recent question here and Jack's answer was a negative stagger value.

 Happy tweening.

:)

 

  • Like 5
Link to post
Share on other sites
On 1/10/2014 at 9:05 PM, GreenSock said:

We may actually alter the way the stagger methods work in a future version of GSAP so that when a negative stagger is used, it simply reverses the array internally, thus avoiding the "back-shift" timing thing. If anyone wants to chime in and vote for what they think is the most "intuitive" behavior, please do. 

 

Sorry, I quoted from another post previously. Now I got the one i was actually referring to: @GreenSock  said in 2014 that they might change the way how potential -1s (or more) time problems are handled. I was just wondering, if this happened, since we have 2018 now... :-)

Thank you!

Link to post
Share on other sites

Yep, using a negative stagger is absolutely fine - it'll go through the array in reverse order. 

  • Like 4
Link to post
Share on other sites
  • 2 years later...

Hello from the future. In GSAP3, FYI, neither a negative stagger value nor stagger: { from: 'end' } are doing squat for me. I still have to manually gather my group of elements into a JS array and reverse it. I am using an "each" rather than an "amount," if that makes a difference, although I don't see why it should...

Link to post
Share on other sites

I recreated your pen, yeah, negative works AND from: 'end' work. Unfortunately, it would be difficult to extract a minimal demo from what I'm working on right now (with a timeline that's almost 2,000 lines of JS at this point). If it makes a difference, I am working in React, using Gatsby, and have the timeline set up in a useEffect hook... I will try some more things and get back to you, thanks for the prompt response!

Link to post
Share on other sites
12 minutes ago, billyZduke said:

I recreated your pen, yeah, negative works AND from: 'end' work. Unfortunately, it would be difficult to extract a minimal demo from what I'm working on right now (with a timeline that's almost 2,000 lines of JS at this point). If it makes a difference, I am working in React, using Gatsby, and have the timeline set up in a useEffect hook... I will try some more things and get back to you, thanks for the prompt response!

No problem. I wonder if maybe whatever you were passing in as the target didn't actually have multiple elements? I'm totally guessing, of course, but that'd definitely explain the lack of staggering. 

 

If you can create a minimal demo with only the absolutely essential code to reproduce the problem, we'd be happy to take a peek. Disclaimer: I'm not a React guy at all, so I may not be able to help with that part. 

  • Like 1
Link to post
Share on other sites

Gahh. Well, it was a React issue... The things I was trying to move are components, and though I was putting the className on them, INSIDE the component it was not passing that className to the actual HTML element getting rendered. My bad.

  • Like 1
Link to post
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.

×