Hi all:
After a couple years of not working w/Flash, I'm starting a new project and I see that Tweener is no longer supported. I've found TweenLite/TweenMax. Is that a good alternative or are there other recommendations?
Thanks.
Hi,
Yes, that is one of the best alternatives, the syntax is also similar to Tweener. But, you will barely notice any difference in performance while using basic tweens (TweenLite/Max will most probably perform better in 'extreme' tweening). You may also need to buy a license depending on the project but you can use it for free in commercial one-time fee projects. Even though Tweener is no longer updated, I would say you cannot go wrong using it but there are newer tween engines (TweenLite, BetweenAS3...) so I think we should use those ![]()
Thanks for the offer!
I've been studying up on the Greensock stuff - it's quite tremendous, but I am stumped on setting up a Timeline for my current project.
Its a repeating animation of a laser beam scanning some papers and goes something like this:
Repeat for 6 unique pieces of paper:
1) Paper moves into place.
2) Laser scans across.
3) Paper moves out of frame - either straight across or it rotates goes down. So the timing of the 2 different paper anims will be different.
I realize there are a few ways to approach this.
What I'm attemping is to append() each animation in a TimelineMax. There are only 6 pieces of paper (each only has one timeline - across or down), and the laser timeline is the same each time.
I setup the laser timeline and then discovered that when it is appended to another timeline, it will only run once due to the way it is instanced.
On the Greensock forum, I found a workaround, but am unable to get it to work.
Here are my attempts and their results:
var laserAni:TimelineMax = new TimelineMax();
laserAni
.to(laser, laserFadeTime, {alpha:1, delay:laserDelay})
.from(laser, laserMoveTime, {x:-250 })
.to(laser, laserFadeTime, {alpha:0});
var allAni:TimelineMax = new TimelineMax();
//allAni.append(laserAni);//Only runs once if repeated
//allAni.append( new TweenMax(laserAni, laserAni.duration, {currentTime:laserAni.duration} ) );//Implicit coercion of a value of type Function to an unrelated type Number.
//allAni.append( new TweenMax(laserAni, laserAni.duration, {} ) );//Implicit coercion of a value of type Function to an unrelated type Number.
//allAni.append( new TweenMax(laserAni, 3, {currentTime:laserAni.duration} ) );//Property currentTime not found on com.greensock.TimelineMax and there is no default value.
allAni.append( new TweenMax(laserAni, 3, {} ) );//Only runs once if repeated
allAni.append( new TweenMax(laserAni, 3, {} ) );
So the question is: what is the most elegant way to repeat the laser timeline without having to reconstruct it each time?
Any suggestions will be appreciated.
Thanks much.
Here's the thing about Flash and your end users system. When you try to set up animation sequences by a certain duration of time, the clients computer may not be fast enough to be ready when that duration comes around. I always daisy chain my animations based on events.
Here's a quick TweenLite example of an animation happening and then triggering another function once it is complete (handling your need for differences in page animation durations):
import com.greensock.TweenLite;
import com.greensock.easing.Quad;
// create a rectangle shape
var c:Sprite = new Sprite();
c.graphics.beginFill(0xFF0000,1);
c.graphics.drawRect(0,0,100,100);
c.graphics.endFill();
addChild(c);
// animate the box from position 0,0 to 100,0 (to the right, 100 pixels, over 1 second)
// the easing is just for fun....
TweenLite.to(c,1,{x:100,easing:Quad.easeInOut,onComplete:nextAnimation });
function nextAnimation():void
{
// this fires off after the box is at 100,0..
// now move it down to 100,100 (just move it down)
TweenLite.to(c,1,{y:100,easing:Quad.easeInOut});
}
What happened there is I made a red square, added it to the stage and then animated it from 0,0 to 100,0.. then by using the onComplete property and specifying a function name it will call that function as soon as the animation was over. Once it is, that function is called and then I move the box from 100,0 to 100,100...
Point of all of this is you can "daisy chain" your animations on their completedness rather than a specific "time". Being your clients machine may be slower than you suspect, things can take longer to render. So let TweenLite use the onComplete event to trigger the next part of the animation. Then you're guaranteed the animation will happen only after the clients machine has completed the current animation, no matter its speed.
That's how I'd approach it.
TweenLite.to(c,1,{x:100,easing:Quad.easeInOut,onComplete:nextAnimation });
FYI, it's ease not easing:
TweenLite.to(c,1,{x:100,ease:Quad.easeInOut,onComplete:nextAnimation });
Using easing won't produce any error either, TweenLite will just ignore it.
And, TweenLite/Max is not a 'good' choice - it is hands down the very best tweening platform for AS3, none of the others even come close in terms of features, or performance.
Yep ease is the property.
Daisy chaining is one way to do it but it does make you continuously need to supply the method name. Not really a bad thing but you can also utilize a TweenEvent which will fire off when your animations do various things.
I use it more to make adjustments as a tween is updating (TweenEvent.UPDATE). It has a COMPLETE handler as well. You can keep track of where you are in your animation in many ways and use a single function that gets called any time a tween completes. Then that function is reused over and over and does the proper thing based on what you're doing. Then you centralize all the events into that one function rather than making a bunch of functions to daisy chain. It's just another strategy that can be cleaner for much more complex tween situations.
Thanks sinious.
This is helpful. I'm using a combination of timelines and functions (my animation is not very processor intensive).
A function is useful in this case because I can pass it an MC, and so only write the multipstep animation one time.
Question:
If I have a button to pause a timeline that has been called inside a function, how do I address it (ie, get it's name)?
For example on an MC named 'scanner' I have:
function runEnv2Ani(who:MovieClip):void
{
var env2Ani:TimelineMax = new TimelineMax();
env2Ani
// Env2 X
.fromTo(who, envTravelTime, {x:envStartX}, {x:envScanX, delay: envStartDelay} )
.to ...
}
I want a button on the root to pause env2Ani IF its running.
If I do this:
scanner.env2Ani.pause();
I get this error:
A term is undefined and has no properties.
I also tried:
scanner.runEnv2Ani.env2Ani.pause();
If a timeline named 'allAni' is on the root of an MC, this works:
scanner.pause();
so I assume Flash is not finding env2Ani because it's inside a function.
Do you know how I can test if env2Ani is there and then pause it?
Or perhaps there is a better way to pull this off?
Message was edited by: voxL
If you need to be able to pause things you can make a public or global variable that you can continually set the current animation to. For example in a frame script:
var currentAnimation:TweenLite;
Then when creating an animation using TweenLite.to() just assign it, e.g.:
currentAnimation = TweenLite.to(c,1,{x:100});
That will assign the TweenLite reference to currentAnimation. Then at any time you can use the methods pause(), play(), resume(), restart().
e.g. when you want to pause:
currentAnimation.pause();
Then whatever is assigned to that TweenLite will pause. When you want to resume just run:
currentAnimation.resume();
Then at the end whatever onComplete function you listed will still fire off.
North America
Europe, Middle East and Africa
Asia Pacific