Jump to content
Search Community

reverseoncomplete mutiple tweens (SOLVED)

carlosfandang test
Moderator Tag

Recommended Posts

Hi, I'm a real noob, but I have successfully managed to create some quite complex animations, but I'm being really thick I'm sure, so be nice. Having read the forum i think quite thoroughly about reverse, oncomplete, etc ... I just can't work out what to do (think because I have multiple timelines to reverse and delay).

 

Here's the problem in a nutshell:

 

1) I have a very complex animation with numerous assets (movieclips) that fade, scale, etc

2) I have 4 content areas - each button animates the assets (same assets) in a different way from the same start point and then loads a different external swfs

3) This is fine I can do that no problem - 4 different timelines attached to each button eventlistener and loading / unloading swf's - got that sussed.

4) But, what I'm stuck with is "reverse", then play.

 

I can get each button to animate the assets from the same start point and even get the home button to reset to original starting point using reverse of the timelines. What I can't fathom (probably 'cos I'm stupid!) is how to get a button to reverse the other 3 buttons animations to the start point and then trigger the animation for that button (i.e a delay or oncomplete of the reverse).

 

I have enclosed a simple example of 4 squares (schoolboy version of my real file) that animate on clicking the colour "button" and a home (reset) button that reverses all animations to start point. But now stuck - For instance, if I clicked the red button (red square enlarges) and then the blue button - how do I get the red square timeline to reverse and oncomplete, the blue timeline then plays (they are both simultaneous currently). AND the home button obviously has to reverse any timeline open at the time??? :-(

 

Would really appreciate a pointer - always willing to learn, just becoming hairless in the process!! Thanks

 

import com.greensock.*;
import com.greensock.plugins.*;
import com.greensock.easing.*;
TweenPlugin.activate([ColorTransformPlugin, FrameLabelPlugin, BezierThroughPlugin, RemoveTintPlugin, SetSizePlugin, FramePlugin, BlurFilterPlugin, TransformMatrixPlugin, GlowFilterPlugin, RoundPropsPlugin, ColorMatrixFilterPlugin, ScrollRectPlugin, EndArrayPlugin, DropShadowFilterPlugin, ShortRotationPlugin, VisiblePlugin, BevelFilterPlugin, BezierPlugin, QuaternionsPlugin, VolumePlugin, AutoAlphaPlugin, HexColorsPlugin, TintPlugin]);


//event listeners for buttons
reset.addEventListener(MouseEvent.CLICK, resetclick);
redbtn.addEventListener(MouseEvent.CLICK, redclick);
bluebtn.addEventListener(MouseEvent.CLICK, blueclick);
greenbtn.addEventListener(MouseEvent.CLICK, greenclick);
pinkbtn.addEventListener(MouseEvent.CLICK, pinkclick);



//functions for buttons
function resetclick(event:MouseEvent):void {
redtimeline.reverse();
bluetimeline.reverse();
greentimeline.reverse();
pinktimeline.reverse();
}

function redclick(event:MouseEvent):void {
redtimeline.play();
bluetimeline.reverse();
greentimeline.reverse();
pinktimeline.reverse();
}

function blueclick(event:MouseEvent):void {
bluetimeline.play();
redtimeline.reverse();
greentimeline.reverse();
pinktimeline.reverse();
}

function greenclick(event:MouseEvent):void {
greentimeline.play();
redtimeline.reverse();
bluetimeline.reverse();
pinktimeline.reverse();
}

function pinkclick(event:MouseEvent):void {
pinktimeline.play();
redtimeline.reverse();
bluetimeline.reverse();
greentimeline.reverse();
}


//Greensock actions on squares

//red square
var redtimeline:TimelineMax = new TimelineMax();
redtimeline.insertMultiple([
new TweenMax(redsq, 1, {glowFilter:{color:0xffffff, alpha:1, blurX:25, blurY:25}}),
new TweenMax(redsq, 1, {scaleX:1.5, scaleY:1.5}), 
], 0);
redtimeline.pause();

//blue square
var bluetimeline:TimelineMax = new TimelineMax();
bluetimeline.insertMultiple([
new TweenMax(bluesq, 1, {glowFilter:{color:0xffffff, alpha:1, blurX:25, blurY:25}}),
new TweenMax(bluesq, 1, {scaleX:1.5, scaleY:1.5}), 
], 0);
bluetimeline.pause();

//green square
var greentimeline:TimelineMax = new TimelineMax();
greentimeline.insertMultiple([
new TweenMax(greensq, 1, {glowFilter:{color:0xffffff, alpha:1, blurX:25, blurY:25}}),
new TweenMax(greensq, 1, {scaleX:1.5, scaleY:1.5}), 
], 0);
greentimeline.pause();

//pink square
var pinktimeline:TimelineMax = new TimelineMax();
pinktimeline.insertMultiple([
new TweenMax(pinksq, 1, {glowFilter:{color:0xffffff, alpha:1, blurX:25, blurY:25}}),
new TweenMax(pinksq, 1, {scaleX:1.5, scaleY:1.5}), 
], 0);
pinktimeline.pause();

Link to comment
Share on other sites

There are many ways to approach this actually. Here are a few ideas for you:

 

1) Tween the currentTime property of your timeline(s) that you want to reverse and then either use an onComplete to trigger the next one to play, or even sequence that one into another TimelineLite. For example:

 

TweenLite.to(myTimeline1, myTimeline1.currentTime, {currentTime:0, ease:Linear.easeNone, onComplete:myTimeline2.play});

 

2) Use the onReverseComplete special property in the timeline like:

 

myTimeline1.vars.onReverseComplete = myTimeline2.play;
myTimeline1.reverse();

 

There are other ways too, but I don't want to confuse anyone :)

Link to comment
Share on other sites

Thanks for the quick reply.

 

I have tried your suggestions and slowly understanding how they they work. I was fine setting each of your suggestions up for 1 button to reverse and play another, but got confused trying to do it for all for buttons and associated timelines.

 

Now I'm trying to figure out 2 things:

 

1) If a button is set to reverse timeline1 and then play timeline2 - how do I also get that button to reverse timeline3 and 4 aswell. I have 4 buttons which need to reverse 3 other timelines and then play it's own timeline. I tried to duplicate all the oncompletes, but it barfed.

 

2) So then I looked at currentTime - I duplicated the currentTime code x 3 to put timeline2/3/4 to 0 and then play timeline1 (redtimeline below).

 

function redclick(event:MouseEvent):void {
TweenMax.to(bluetimeline, bluetimeline.currentTime, {currentTime:0, ease:Linear.easeNone, onComplete:redtimeline.play});
TweenMax.to(greentimeline, greentimeline.currentTime, {currentTime:0, ease:Linear.easeNone, onComplete:redtimeline.play});
TweenMax.to(pinktimeline, pinktimeline.currentTime, {currentTime:0, ease:Linear.easeNone, onComplete:redtimeline.play});
}

 

That worked, but I'm having trouble figuring out how to ensure the timelines pause when they are set back to currentTime: 0 - basically all the timelines then play from 0. That makes sense, but where do I put the pause function - tried it in the { }, but no joy.

 

Sorry, I suspect it's really simple, but my learning curve is a bit jagged!! Thanks

Link to comment
Share on other sites

You might be overthinking it - what about doing something like:

 

var timelines:Array = [redTimeline, blueTimeline, pinkTimeline, greenTimeline];

function activateTimeline(timeline:TimelineLite):void {
   var sequence:TimelineLite = new TimelineLite({onComplete:timeline.play});
   var i:int = timelines.length;
   while (i--) {
       if (timelines[i] != timeline) {
           timelines[i].pause();
           sequence.insert( new TweenLite(timelines[i], timelines[i].currentTime, {currentTime:0, ease:Linear.easeNone}) );
       }
   }
}

 

Then, you can simply call activateTimeline(redTimeline) and it'll handle it from there.

 

As far as pausing the timelines after they reach 0, I'd actually recommend pausing them first before you tween them. Not only would it be easier for you (as opposed to trying to do stuff onComplete), but it's more efficient anyway.

Link to comment
Share on other sites

Thanks, I'll have a look into this when I have a moment. With regards to the pause, I did put an initial pause into the code at the beginning, but it seems that as soon as I call for the currentTime to be zero, it then starts playing even though the code is paused right from the start - don't know, presumably currenttime asks to return to zero and then says "start playing"!!

 

Thanks and will look into the arrays.

Link to comment
Share on other sites

...but it seems that as soon as I call for the currentTime to be zero, it then starts playing even though the code is paused right from the start - don't know, presumably currenttime asks to return to zero and then says "start playing"!!

 

Nope, it definitely doesn't automatically force a play() when it its zero. It will honor your pause(). If you're having trouble with that, just post an example FLA that demonstrates it doing that odd behavior and we'll take a peek.

Link to comment
Share on other sites

Ok, now I'm massively confused, I clearly have not got the hang of this at all. I have attached a new file:

 

1) One black square - 3 timelines

2) Click each button and the black square is meant to go to the relevant coloured holder, but return to the black holder first (i.e if in the red holder and I click blue, it's meant to return to the black holder first then go to blue).

 

I'm getting stupidly confused having tried oncompletereverse, etc - anybody fancy helping a dunce out?

 

Thanks

Link to comment
Share on other sites

I'm so glad you posted the sample FLA - it helped me see what you're trying to do. In the simplified example, you probably don't even need TimelineLite/Max because you could just do a simple tween back to the center and a delayed tween out to whichever color you want, but I realize your actual production file will have a lot more going on and it may be very useful to have all the tweens set up in a TimelineLite/Max, so I edited your example FLA to make it work with timelines. See attached. There are several ways to accomplish this effect, but I chose what I think is probably the most flexible.

Link to comment
Share on other sites

Genius, thank you so much for your trouble, much appreciated. Looking at the file, I understand the concept of what you have done, but will now dig around on here using the file as a reference so that I can learn more and thoroughly understand exactly what you have kindly posted for me.

 

As you said, I have complex animations using all sorts of scaling, shearing, alpha, etc - so this will be invaluable and I will be happy to post it up when I'm done and show that even Noobs can persevere!!

 

Thanks again

Link to comment
Share on other sites

I was hoping I could get one more piece of advice on the code greensock posted above. When the timeline reverses and then plays a new timeline it is instantaneous.

 

I've tried a "delayedCall" / "delay" in the triggerqueue and activetimeline functions but can't seem to get it to work. I'm trying to put a pause between the reversed timeline and the next timeline that plays. I obviously don't want to put that pause in the associated timeline itself, because I don't want the delay when a button is first clicked and isn't reversing anything else.

 

I could create a duplicate timeline with a pause in, but it seems crazy and I suspect there is a simple way to put the pause in the function.

 

Any help as always much appreciated.

Link to comment
Share on other sites

Yeah, you don't need to create another whole timeline for that. A delayedCall() should work, but the problem is that you must think about cases where the user might click various things quickly, so if they click blue and it spawns a delayedCall() that'll wait 1 second to play it and then the user clicks green 0.5 seconds later and it spawns another delayedCall() to play green in 1 second, it'll actually start playing blue in 0.5 seconds when that first delayedCall() expires and does its job. See what I mean?

 

One solution would be to call TweenLite.killTweensOf(activateTimeline) or keep track of the delayedCall() and kill() it when necessary like:

function triggerQueue():void {
       TweenLite.killTweensOf(activateTimeline);
activeTimeline = queuedTimeline;
if (activeTimeline != null) {
	TweenLite.delayedCall(activateTimeline, [activeTimeline]);
}
}

 

Alternatively, inside the triggerQueue() method, you could add a delay to the activeTimeline and then restart() it and use the first parameter of restart() to tell it to include the delay in the restart. Like this:

 

function triggerQueue():void {
activeTimeline = queuedTimeline;
if (activeTimeline != null) {
               activeTimeline.delay = 1;
               activeTimeline.restart(true);
               queuedTimeline = null;
}
}

Link to comment
Share on other sites

Brilliant thanks, I will look into that.

 

With regards to clicking things quickly, actually I already decided that because my animations are quite complex I didn't want "click happy" problems, so each menu button already disables the mouseenabled property on the buttons until the tweens have finished - clunky, but it forces people to wait for the tweens to finish (they are only a few seconds long anyway).

 

Appreciate your continued help.

Link to comment
Share on other sites

  • 2 weeks later...

Hello Mr Greensock,

 

I've been playing around with all of this and I'm learning fast, but as usual I have a question. I have enclosed an updated file so you can see what I'm trying to do (albeit a much simpler version of my animations). So I'm using the triggerQueue() as you kindly pointed out. In the enclosed example, the menus move the relevant square with a "1" delay on the reversecomplete as your code answered my last question (thanks).

 

I have some animation that runs all the time (i.e the 3 balls in the example - when ball1 anim. completes it restarts all ball timelines again). So far so good. What I want to do, is when a menu button is clicked, the balls fade (turn alpha to zero), note ... the animation still continues that's fine. That was straightforward putting the function call inside "function activateTimeline(tl:TimelineMax)". So, whenever a menu bttn is clicked the ball animation is "alpha'd out".

 

This is what I'm stuck on - when the "reset bttn" is clicked, I want to have the balls appear again (alpha:1) WHEN the open timeline.reverse completes. Whilst I can easily put the function "ballsappear()" inside the reset function and use a timeline delay (see commented out code at bottom of actionscript in file), it's not quite there. You see in the file that one animation is longer than the others, so the delay works great for some but appears to soon for others. I also wanted to have the reverse run at a faster speed than the "play".

 

I can't work out how to run "ballsappear()" ONLY when the reset button is clicked and whatever timeline.reverse has completed. My scripting is still relatively new and I tried:

 

function resetclick(event:MouseEvent):void {
if (activeTimeline != null) {
	activeTimeline.reverse({onComplete: ballsappear});
}
}

 

and various different other options, but to no avail. AM I BEING REALLY STUPID HERE ??!!

 

Many thanks for working hard to educate us numpties.

 

Best regards

 

Fandang

menuclick.fla.zip

Link to comment
Share on other sites

If you want them to fade in when the reverse completes, why not put that code inside the onReverseComplete function (triggerQueue() in this case)? If you only want it to happen after the reset button is clicked, you can set a Boolean flag when it's clicked and look for that Boolean variable in triggerQueue() and conditionally run ballsappear().

 

If you want things to run at a different pace when reversing, you can always alter the timeScale.

 

And if you want to tween a TimelineLite/Max backwards and run an onComplete after it finishes, you can use TimelineMax's tweenTo() like tweenTo(0, {onComplete:myFunction}). It'd be like doing a reverse() but with your own custom onComplete for that particular time (as opposed to a reverse() with an onReverseComplete).

 

I hope that sheds some light on things.

Link to comment
Share on other sites

Thanks for the response again, unfortunately I'm so fresh with scripting I haven't worked out how to just set a boolean variable for the reset function only in triggerQueue (I'll keep looking at it, but as I said, it's all trial and error with me!).

 

So I successfully implemented the tweenTo oncomplete function which achieved what I wanted apart from the timescale. I see you covered this topic with user gerrydesign. All my reverse animations run at timescale = 2, whilst play runs at timescale = 1. So sadly, the reset tweenTo reverse is great apart from it runs at the timelines original speed.

 

Thanks anyway, will have to keep trying to work things out.

 

Cheers

Link to comment
Share on other sites

Well, I decided to take the easy route based on what knowledge I have. I simply created a blank timeline (i.e no animation) to replace the reset click. Now the "home reset" works at double speed on the reverse and fades in the assets animation for the homepage - not good coding I suppose, but works fine. Of course I had to reduce the delay between animations, as that takes me back to my original problem of not having a delay from when you're technically on the homepage!

 

Thanks for the continued help.

Link to comment
Share on other sites

All my reverse animations run at timescale = 2, whilst play runs at timescale = 1. So sadly, the reset tweenTo reverse is great apart from it runs at the timelines original speed.

 

If you want the tweenTo() to run at a different speed, you have several options:

 

1) Put it into a TimelineLite and change the timeScale of the TimelineLite. Kinda like:

var t:TimelineLite = new TimelineLite({timeScale:2});
t.append( myTimeline.tweenTo(1) );

 

2) Create the tween yourself and either make the duration shorter or use TweenMax so that you can alter the timeScale:

 

myTimeline.pause();
var destinationTime:Number = 1;
var duration:Number = Math.abs(myTimeline.currentTime - destinationTime);
var tween:TweenMax = new TweenMax(myTimeline, duration, {currentTime:destinationTime, ease:Linear.easeNone});
tween.timeScale = 2;

Link to comment
Share on other sites

Genius, thank you so much. I'm really having to study this hard to get to grips with it, but thank you again.

 

Just to share with other users on the forum looking for similar functionality, the final solution is provided below - and to be honest "Greensock" pretty much did it all. Basically, it provides the following:

 


  • 1) Each menu button has its own animation - plays at normal speed.
    2) Each animation will run, after a reverse (reverse plays at twice speed) of the other animations and a delay between them.
    3) The "reset" function also has an oncomplete (this is separate - I use it because it affects other animation unrelated to the menu animations).

 

The menu functionality:

var activeTimeline:TimelineMax;
var queuedTimeline:TimelineMax;

function activateTimeline(tl:TimelineMax):void {
if (activeTimeline != tl && activeTimeline != null && activeTimeline.currentTime != 0) {
	queuedTimeline = tl;
	activeTimeline.reverse();
	activeTimeline.timeScale = 2;

} else {
	queuedTimeline = null;
	activeTimeline = tl;
	activeTimeline.play();
	activeTimeline.timeScale = 1;


}
}

function triggerQueue():void {
activeTimeline = queuedTimeline;
if (activeTimeline != null) {
	activeTimeline.delay = 0.75;
	activeTimeline.timeScale = 1;
               activeTimeline.restart(true);
               queuedTimeline = null;
}
}


function resetclick(event:MouseEvent):void {
if (activeTimeline != null) {
var t:TimelineLite = new TimelineLite({timeScale:2});
t.append( activeTimeline.tweenTo(0, {onComplete: myfunction}) );
	}

}

 

The code at the beginning of each separate menu animation:

var yourtimeline:TimelineMax = new TimelineMax({onReverseComplete:triggerQueue, paused:true})

 

The code in the menu button listener:

function menuclick(event:MouseEvent):void {
activateTimeline(yourtimeline);

 

Brilliant, thank you for all the help and hopefully this may prove useful to those looking to run animations from menu clicks with a sort of oncomplete function. Fla enclosed.

 

Cheers Fandang

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...