Jump to content
Search Community

Subtitles using TweenLite [SOLVED]

typofonic test
Moderator Tag

Recommended Posts

Hi,

 

I'm working on a flash animation that I want to add subtitles to.

 

The subtitles should fade in over 2 seconds with an easeOut and before being replaced with a new subtitles they should again fade out for 2 seconds with an easeOut.

 

I have attached a picture of how it works in the timeline. Pretty simple:

1. An actionscript changes the subtitle text

2. The text fades in with an EaseOut

3. The text fades out with an EaseOut

4. This gets repeated over and over.

 

I'm no actionscript wizard, but doing this manually in the timeline is extremely timeconsuming so it could be great to use TweenLite instead.

 

I have tried to use v10 of TweenLite and their onComplete and onStart functions, but they keep on getting executed BEFORE the previous tween has finished. Probably a problem with the tweens getting overwritten or something like that. Unfortunately I wasn't able to fix it with neither the OverwriteManager or any other workarounds, so I switched to v11 to be able to use the TimelineLite function — but I can't make that work either :(

 

I have imported all the necesary files in the first frame and then whenever I need to fade in a new subtitle I have the following code:

 

var myTimeline:TimelineLite = new TimelineLite();
myTimeline.insertMultiple( [TweenLite.to(undertekster,1 ,{alpha:0, ease:Back.easeOut}), TweenLite.to(undertekster,1 ,{alpha:1, ease:Back.easeOut, onStart:skiftUndertekst(10)})], 0, TweenAlign.SEQUENCE);

 

The function skiftUndertekst(10) simple changes the text of the subtitle. As far as I understand TweenAlign.SEQUENCE should make the tweens play in sequence (so that when one tween has finished, the next one starts etc.) That's exactly what I want to accomplish but it just doesn't work.

 

TweenLite seems a perfect choice for creating subtitles, so it could be nice to make it work.

 

Any ideas, tips, suggestions or anything are greatly appreciated.

Link to comment
Share on other sites

The problem is that you're putting the "()" after the function which tells Flash to call the function immediately. Use the onStartParams or onCompleteParams to define the parameters you want passed to the function (if any) when it is called:

 

BAD: TweenLite.to(undertekster,1 ,{alpha:1, onStart:skiftUndertekst(10)});

GOOD: TweenLite.to(undertekster,1 ,{alpha:1, onStart:skiftUndertekst, onStartParams:[10]});

Link to comment
Share on other sites

Hi,

 

Thanks a lot Jack! It worked perfectly! Now the fadeIn doesn't start before the previous fadeOut has completed. And to make it more easy to use I changed the framenumber to a label, which works just as well.

 

However a new problem has occured — it seems the tweens get overwritten. The fade from the 1st subtitle to the 2nd (frame 'tre') works great, however the fade from the 2nd to the 3rd (frame 'fire') subtitle doesn't work. The text just get replaced instantly without any fade.

 

I've tried using all the possible values of the the OverwriteManager (putting it in the first frame), using the syntax below but it still doesn't fix it:

OverwriteManager.init(OverwriteManager.NONE);

 

I've attached a screenshot of my timeline with the scripts. The movieclip in the timeline is 'undertekster', and the scripts you see are the ones below:

 

1st subtitle:

TweenLite.to(undertekster,1 ,{alpha:1, ease:Back.easeOut});

 

2nd subtitle:

var myTimeline:TimelineLite = new TimelineLite();
myTimeline.insertMultiple( [TweenLite.to(undertekster,2 ,{alpha:0, ease:Back.easeOut}), TweenLite.to(undertekster,2 ,{alpha:2, ease:Back.easeOut, onStart:skiftUndertekst, onStartParams:['tre']})], 0, TweenAlign.SEQUENCE);

 

3rd subtitle:

myTimeline.insertMultiple( [TweenLite.to(undertekster,2 ,{alpha:0, ease:Back.easeOut}), TweenLite.to(undertekster,2 ,{alpha:2, ease:Back.easeOut, onStart:skiftUndertekst, onStartParams:['fire']})], 0, TweenAlign.SEQUENCE);

 

4rth subtitle:

myTimeline.insertMultiple( [TweenLite.to(undertekster,2 ,{alpha:0, ease:Back.easeOut}), TweenLite.to(undertekster,2 ,{alpha:2, ease:Back.easeOut, onStart:skiftUndertekst, onStartParams:['fem']})], 0, TweenAlign.SEQUENCE);

 

I'd really appreciate any ideas you might have. I'm sure it would help a lot of people wanting to make subtitles with flash. Also if this is can be fixed , it can be used for all the 10 animations I've made.

Link to comment
Share on other sites

Looks to me like the problem is that you're inserting all your tweens at the same spot on the timeline. In your insertMultiple(), the 2nd parameter controls where those tweens get placed on the timeline. You're using 0 for everything. I suspect the confusion is that you're defining the alignment as TweenAlign.SEQUENCE, but that controls only how those new tweens relate to each other. In other words, if you are inserting 3 tweens at the zero position and you're aligning them as a sequence, it will put them back-to-back starting at time zero. I suspect you intended to add them AFTER all the existing tweens in the timeline, right? If so, you can either use appendMultiple() which will automatically use the END of the timeline as the insertion point, or use the timeline's duration property as the insertion value in insertMultiple().

 

Make sense now?

Link to comment
Share on other sites

That's because you didn't remove the time parameter (if you're appending, there's no need to define an insertion point/time).

 

BAD: myTimeline.appendMultiple( [...tweens...], 0, TweenAlign.SEQUENCE);

GOOD: myTimeline.appendMultiple( [...tweens...], TweenAlign.SEQUENCE);

Link to comment
Share on other sites

GOOD: myTimeline.appendMultiple( [...tweens...], TweenAlign.SEQUENCE);

 

Thanks! This actually fixed the problem — kind of. Now the subtitles fadeOut, change their text and Fade in. Unfortunately this only happens if the fades/frame actions are close enough — that is if the tween of frame-action 2 is in the progress when the playhead gets to frame-action 3 and begins the next tween. Which means that the script works only if the subtitles should begin fading out, just after they have faded in — not very useful for subtitles unfortunately. If the fades/frame actions aren't close enough nothing happens.

 

So to say it in another way, currently it only works like this:

— which means you don't have any time to read the subtitles before they disappear again.

 

But it should work like this:

<-------------------------- text remains faded in --------------------------> <------------- text remains faded in ------------->

 

The time the subtitle remain faded in depends on the duration of each part of the animation — it varies. But it is controlled by the timeline: whenever the playhead hits a new frame action it should begin its fadeOut>Change_text>fadeIn action.

 

So how can the actions be changed so that it still works, when the text remains faded in for some time before fading out again.

 

Thanks for all of you help — I know I have many questions :) I am a novice when it comes to both actionscript and TweenLite.

 

I imagine the script just needs a minor tweak?

Link to comment
Share on other sites

You have complete control over the timing of everything - you can either insert() (or insertMultiple()) at specific times, or if you're appending with append() or appendMultiple(), you can use the "delay" special property in tweens to offset them. Like:

myTimeline.append( new TweenLite(subhead1, 1, {autoAlpha:1}) );
myTimeline.append( new TweenLite(subhead1, 1, {autoAlpha:0, delay:10}) ); //wait 10 seconds before fading out
myTimeline.append( new TweenLite(subhead2, 1, {autoAlpha:1}) );
myTimeline.append( new TweenLite(subhead2, 1, {autoAlpha:0, delay:8}) ); //wait 8 seconds before fading out
...

 

Or, again, you can just insert() at very specific spots on the timeline, like:

 

myTimeline.insert( new TweenLite(subhead1, 1, {autoAlpha:1}), 0);
myTimeline.insert( new TweenLite(subhead1, 1, {autoAlpha:0}), 11); //inserts the tween at exactly the 11-second point
...

 

And if you're going to have them all animate with the same kind of timing (same amount of time between them all), you could use the TweenMax.allTo() method, like:

 

var subheads:Array = [subhead1, subhead2, subhead3];
myTimeline.insertMultiple( TweenMax.allTo(subheads, 1, {autoAlpha:1}, 10), 0);
myTimeline.insertMultiple( TweenMax.allTo(subheads, 1, {autoAlpha:0, delay:9}, 10), 0);

 

Just a few ideas :)

Link to comment
Share on other sites

Thanks for all your examples!

As far as I can see all of the examples above insert code at specific times in the timeline using Actionscript. However specifying in ActionScript where to insert the tweens would make it very difficult to put it in the right frame of the timeline, since its frame based animation where things are moved around all the time. So whenever part of an animation is moved, all the animations after this point have to be pushed forward or backward on the timeline which means that all the actionscript would have to be modified because the time has changed. If the tweens could just be moved with the animation (as they can with frame based actions) they could much more easily be moved around.

 

Can't the code simply just begin tweening whenever it reaches a tween action on the timeline like this:

myTimeline.insertMultiple( [TweenLite.to(undertekster,2 ,{alpha:0, ease:Back.easeOut}), TweenLite.to(undertekster,2 ,{alpha:2, ease:Back.easeOut, onStart:skiftUndertekst, onStartParams:['tre']})], TweenAlign.SEQUENCE);

 

Then do its thing, and then only start the next tween when it reaches the next tween action on the timeline?

 

The only thing missing in the code you've helped me with already, is that it doesn't work unless the tweens run just after each other (if the tweens overlap). I don't think I'm explaining it very well, so I'm wondering if I can quickly send you part of the animation file off-forum (can't post it since its actually confidential, until the product is released), so you can see how it's setup and what I mean? It seems like its just a small fix/bug.

Link to comment
Share on other sites

Just so you know, you can set a timeline's timing mode to be frames-based instead of time if you prefer, like:

 

var timeline:TimelineLite = new TimelineLite({useFrames:true});

 

Then ALL your duration/delay numbers in tweens that you're putting into that timeline should be in FRAMES, not seconds.

 

You can send me a file offline if you want, but I MUCH prefer that you NOT send me your original file - instead, it generally works better if you can create a separate/new FLA with only enough code to reproduce the problem. That saves me a lot of headaches trying to monkey around with the surrounding code in your FLA and trying to understand what in the world is going on with it :)

Link to comment
Share on other sites

Just so you know, you can set a timeline's timing mode to be frames-based instead of time if you prefer, like:

 

var timeline:TimelineLite = new TimelineLite({useFrames:true});

 

Then ALL your duration/delay numbers in tweens that you're putting into that timeline should be in FRAMES, not seconds.

 

That would help, but one would still have to change most of the actionscript if the animation is moved around. That's why it could be great to have the tweens initiate using frame actions instead of actionscript.

 

You can send me a file offline if you want, but I MUCH prefer that you NOT send me your original file - instead, it generally works better if you can create a separate/new FLA with only enough code to reproduce the problem. That saves me a lot of headaches trying to monkey around with the surrounding code in your FLA and trying to understand what in the world is going on with it :)

 

Thanks a lot man — I really appreciate it! I have sent you a file with only the most necessary content.

Link to comment
Share on other sites

Wait, you're trying to use the IDE timeline with actions dispersed on various frames to populate a TimelineLite? If you're trying to do this hybrid approach, why not just put tweens directly in the keyframes on your IDE timeline? Then if you add/remove frames, the tweens move with your adjustments. Maybe I'm still misunderstanding (sorry, I'm working against some high-pressure deadlines so I don't have much time to dig into this). Remember, you can set useFrames:true if you need your tweens to stay syncronized with frames on your IDE timeline.

 

Also, if you build a TimelineLite instance progressively with append() and/or appendMultiple(), you can easily make adjustments to tweens early in the sequence and all the ones after it will be adjusted as well (as opposed to using insert() and insertMultiple() which lock you in to absolute times/frames).

Link to comment
Share on other sites

One other idea - you could use the MovieClip's currentFrame as the insertion point into your frames-based TimelineLite instance instead of using append() or appendMultiple(). Like:

 

myTimeline.insert( new TweenLite(mc, 1, {autoAlpha:0}), this.currentFrame);

Link to comment
Share on other sites

Wait, you're trying to use the IDE timeline with actions dispersed on various frames to populate a TimelineLite? If you're trying to do this hybrid approach, why not just put tweens directly in the keyframes on your IDE timeline? Then if you add/remove frames, the tweens move with your adjustments.

 

Actually that was what I did in the beginning, but it was just _extremely_ time consuming. Some of the reasons why I'm not doing this are:

1. It's very time consuming manually setting up tweens with fadeIn, fadeOut and EaseOut for each subtitle (the Motion Presets in Flash CS4 don't really help)

2. It's very difficult moving the timeline around and putting it in submovieclips and scaling it up and down (I have to use the Select Multiple frames tool a lot)

3. It's very timeconsuming changing the fade times for the clip (it could be nice to set it one place)

4. And more :)

 

In total I have around 500 subtitles in this project (in 10 movies) which is why it could be nice to be able to script it.

 

Maybe I'm still misunderstanding (sorry, I'm working against some high-pressure deadlines so I don't have much time to dig into this).

No problem man. I really appreciate that you're taking your time helping me with this, and I can imagine you have lots of other Flash projects to work on yourself (AND coding the TweenLite and TweenMax etc must take a significant amount of your time)! Anyway, it seems like the solution is near.

 

Remember, you can set useFrames:true if you need your tweens to stay syncronized with frames on your IDE timeline.

 

That seems like it is the way to solve the problem combined with _currentframe.

Link to comment
Share on other sites

One other idea - you could use the MovieClip's currentFrame as the insertion point into your frames-based TimelineLite instance instead of using append() or appendMultiple(). Like:

 

myTimeline.insert( new TweenLite(mc, 1, {autoAlpha:0}), this.currentFrame);

 

Yes! That this seems exactly like the way to do it: but how can the code

 

myTimeline.insertMultiple( [TweenLite.to(undertekster,2 ,{alpha:0, ease:Back.easeOut}), TweenLite.to(undertekster,2 ,{alpha:2, ease:Back.easeOut, onStart:skiftUndertekst, onStartParams:['tre']})], TweenAlign.SEQUENCE);

 

be changed so that it begins the tween sequence at the currentframe and then after it has made its first fadeOut ( myTimeline.insert( new TweenLite(mc, 1, {autoAlpha:0}), this.currentFrame) ), it runs this:

TweenLite.to(undertekster,1 ,{alpha:2, ease:Back.easeOut, onStart:skiftUndertekst, onStartParams:['tre']})

 

I assume I have to use insertMultiple instead of insert in my case?

 

I have tried constructing it, but the following code throws out an error:

myTimeline.insertMultiple( [new TweenLite(underskrifter, 1, {alpha:0, ease:Back.easeOut}), this.currentFrame), TweenLite.to(undertekster,1 ,{alpha:1, ease:Back.easeOut, onStart:skiftUndertekst, onStartParams:[undertekst]})], TweenAlign.SEQUENCE)]

 

and does this:

myTimeline.insertMultiple( [new TweenLite(underskrifter, 1, {alpha:0, ease:Back.easeOut}), this.currentFrame), new TweenLite(undertekster,1 ,{alpha:1, ease:Back.easeOut, onStart:skiftUndertekst, onStartParams:[undertekst]})], TweenAlign.SEQUENCE)]

 

Can't figure out what's wrong with it?

 

The tween should just begin fadingOut at the currentframe, and then just after it has faded out, run the skiftUndertekst() function followed by the fadeIn.

Link to comment
Share on other sites

Since I never managed to make the code above work I've tried tried making a seperate FadeIn and FadeOut function. Using frame actions first it fades the existing subtitle out — fadeTekstOut(); — and then later on the timeline it fades a new subtitle in — fadeTekstIn("john-is"). This is the code:

 

function fadeTekstIn(undertekst) {
myTimeline.insert( new TweenLite(undertekster,1 ,{alpha:1, ease:Back.easeOut, onStart:skiftUndertekst, onStartParams:[undertekst]}), this.currentFrame);
}

 

function fadeTekstOut() {
myTimeline.insert( new TweenLite(undertekster, 1, {alpha:0, ease:Back.easeOut}), this.currentFrame);
}

 

In the first frame the TimelineLite is defined like this:

var myTimeline:TimelineLite = new TimelineLite({useFrames:true});

 

so that it counts in frames. However nothing happens whenever the actions run. I just simply can't wrap my head around this problem — anyone who can see what I'm doing wrong?

 

I'll be posting a tutorial on my blog, if I get this to work. There are no ressources on the web about making subtitles for Flash animation, so I think it would help a lot of people.

 

All help is greatly appreciated.

Link to comment
Share on other sites

I don't have much time to dig into this, but here's my initial thought: your TimelineLite instance gets created but you don't populate it until much later. It begins running immediately, so it finished running right away. Then, you added tweens later, but it had already finished running. Try adding a gotoAndPlay() after you add your tweens to make the timeline jump back into action at the spot you want, like this:

 

function fadeTekstOut() {
   myTimeline.insert( new TweenLite(undertekster, 1, {alpha:0, ease:Back.easeOut}), this.currentFrame);
   myTimeline.gotoAndPlay(this.currentFrame);
}

 

Let us know if that helps.

Link to comment
Share on other sites

I'm happy to report that adding:

myTimeline.gotoAndPlay(this.currentFrame);

to both of the actions actually did it! Now it works perfectly!

 

Thanks a lot for your help and patience Jack!

I'll write up a tutorial as soon as we've finished this project. On the 27th of September you'll be able to see a project using TweenLite. Maybe it could be added to the showcase.

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