Jump to content
Search Community

PRESTART event?

moxol test
Moderator Tag

Recommended Posts

What do you mean by "PRE-START" - like a certain amount of seconds or milliseconds before the tween starts? Or on exactly the same frame as when the tween starts, but before it instantiates its starting values?

 

If you want to call a function a certain amount of time before the tween starts, you could just schedule it as such with a delayedCall(). Like if your tween has a delay of 2 seconds, and you want your function to get called about 1 second before, you could do:

 

TweenLite.delayedCall(1, yourFunction);

 

Or you could do the same concept in a TimelineLite (let me know if you need help with that)

 

If you want to call a function right before the tween records its starting values, v12 allows you to simply define an onStart (or onComplete - doesn't matter) in a startAt, like:

 

TweenLite.to(obj, 1, {x:100, startAt:{onStart:yourFunction}});

 

Because the startAt object is just the vars for a tween that gets run immediately right before the tween renders for the first time. It's basically the same as a regular onStart but onStart runs after the beginning values are recorded whereas whatever's in the startAt gets run before.

 

Does that help?

  • Like 1
Link to comment
Share on other sites

Here is example I tried:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
		   xmlns:s="library://ns.adobe.com/flex/spark"
		   xmlns:mx="library://ns.adobe.com/flex/halo"
  click="starts()">

<fx:Declarations>
 <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>

<fx:Script>
 <![CDATA[
 import com.greensock.data.TweenMaxVars;
 import com.greensock.TweenMax;
 import com.greensock.events.TweenEvent;
 import com.greensock.TimelineMax;

 private function starts():void
 {
  var timeline:TimelineMax = new TimelineMax();

  var tweenMaxVars:TweenMaxVars = new TweenMaxVars();
  tweenMaxVars.x(300);
  var tweenMaxVars1:TweenMaxVars = new TweenMaxVars();
  tweenMaxVars1.onStart(function():void {
write();
});
  tweenMaxVars.startAt(tweenMaxVars1);

  var twe:TweenMax = new TweenMax(obj,2, tweenMaxVars);


  timeline.append(twe);

 }

 private function write():void
 {
  for (var counter:Number = 0; counter < 3000; counter++)
  {
trace('beforeStart')
  }
 }
 ]]>
</fx:Script>

<s:Label id="obj" text="object"/>
</s:Application>

 

I need that write() function executes completely before tween starts.

In this example you can see that tween starts while write() function is still executing, which is what I don't want to happen.

Link to comment
Share on other sites

I don't see that at all. What do you mean it starts while write() is executing? ActionScript is single-threaded. Here is code that proves the tween isn't starting until after write() fully executes:

 

 

var timeline:TimelineMax = new TimelineMax();
var tweenMaxVars:TweenMaxVars = new TweenMaxVars();
tweenMaxVars.x(300);
tweenMaxVars.onStart(start);
var tweenMaxVars1:TweenMaxVars = new TweenMaxVars();
tweenMaxVars1.onStart(function():void {
   write();
   });
tweenMaxVars.startAt(tweenMaxVars1);
var twe:TweenMax = new TweenMax(mc1,2,tweenMaxVars);
timeline.append(twe);

function write():void {
   for (var counter:Number = 0; counter < 3000; counter++) {
       trace('beforeStart');
   }
}

function start():void {
trace("start");
}

 

I see "beforeStart" traces out 3000 times before "start" traces. Are you seeing something different?

Link to comment
Share on other sites

I don't see that at all. What do you mean it starts while write() is executing? ActionScript is single-threaded. Here is code that proves the tween isn't starting until after write() fully executes:

 

 

var timeline:TimelineMax = new TimelineMax();
var tweenMaxVars:TweenMaxVars = new TweenMaxVars();
tweenMaxVars.x(300);
tweenMaxVars.onStart(start);
var tweenMaxVars1:TweenMaxVars = new TweenMaxVars();
tweenMaxVars1.onStart(function():void {
write();
});
tweenMaxVars.startAt(tweenMaxVars1);
var twe:TweenMax = new TweenMax(mc1,2,tweenMaxVars);
timeline.append(twe);

function write():void {
for (var counter:Number = 0; counter < 3000; counter++) {
	trace('beforeStart');
}
}

function start():void {
trace("start");
}

 

I see "beforeStart" traces out 3000 times before "start" traces. Are you seeing something different?

 

On screen object moves from 0 to 70-80 and continues to 300,

It doesn't smoothly goes to 300.

Link to comment
Share on other sites

Oh, I know exactly what you're talking about now, and that is expected behavior. In fact, it's a feature (although it may not feel like it in this scenario given your goals). Let me explain...

 

The GreenSock Animation Platform is a synchronized system, unlike many other tweening engines. In other systems, even if you start 2 tweens on the same frame and they have identical durations, they may end at completely different times on completely different frames (not good!). Like if you stacked up a bunch of 1-pixel high boxes vertically on the screen and then tweened each of their "width" properties, you may see more of a wave as they animate across the screen rather than a solid, synchronized wall/edge because each tween's start time was recorded differently. However, GSAP is perfectly synchronized.

 

In your example, you're setting up the tween on a timeline. The timeline begins now, so let's just say the start time is recorded as 0 (to make it easy). The duration of your tween is 2 seconds, so it should finish exactly 2 seconds from now. Let's assume you're moving x from 0 to 200 with a Linear.easeNone ease to make things simple, meaning x should move at 100 pixels per second. No problem.

 

On the next frame, when the tween renders, it fires off your onStart which does a bunch of looping and takes a lot of extra time to process in your function, meaning that the swf's frame rate (for that moment) drops drastically and the next frame doesn't render until 0.5 seconds later. Now at 0.5 seconds, if we're moving at 100 pixels per second, that means x should be at 50 now, so visually it jumps from 0 to 50. That is technically accurate (a feature, not a bug). The only other option is to MOVE your tween so that it won't end on schedule anymore. Most developers don't want that.

 

There are 2 solutions to your dilemma:

  1. Set useFrames:true on your timeline and make sure that you define the duration and/or delay in terms of frames rather than seconds. In frames mode, it doesn't care about time at all - it simply counts frames. That means that if your frame rate bogs down, your tweens will last longer but they will always change the pre-determined amount on each frame.
  2. Create your tween on the next update/tick of the engine AFTER your write() function is called. You can do that using a delayedCall() that has an extremely small duration, like 0.001 and then in that function, you create your tween. Either that or call the undocumented Animation._updateRoot() method from within your

Does that help clarify things?

Link to comment
Share on other sites

Oh, I know exactly what you're talking about now, and that is expected behavior. In fact, it's a feature (although it may not feel like it in this scenario given your goals). Let me explain...

 

The GreenSock Animation Platform is a synchronized system, unlike many other tweening engines. In other systems, even if you start 2 tweens on the same frame and they have identical durations, they may end at completely different times on completely different frames (not good!). Like if you stacked up a bunch of 1-pixel high boxes vertically on the screen and then tweened each of their "width" properties, you may see more of a wave as they animate across the screen rather than a solid, synchronized wall/edge because each tween's start time was recorded differently. However, GSAP is perfectly synchronized.

 

In your example, you're setting up the tween on a timeline. The timeline begins now, so let's just say the start time is recorded as 0 (to make it easy). The duration of your tween is 2 seconds, so it should finish exactly 2 seconds from now. Let's assume you're moving x from 0 to 200 with a Linear.easeNone ease to make things simple, meaning x should move at 100 pixels per second. No problem.

 

On the next frame, when the tween renders, it fires off your onStart which does a bunch of looping and takes a lot of extra time to process in your function, meaning that the swf's frame rate (for that moment) drops drastically and the next frame doesn't render until 0.5 seconds later. Now at 0.5 seconds, if we're moving at 100 pixels per second, that means x should be at 50 now, so visually it jumps from 0 to 50. That is technically accurate (a feature, not a bug). The only other option is to MOVE your tween so that it won't end on schedule anymore. Most developers don't want that.

 

There are 2 solutions to your dilemma:

  1. Set useFrames:true on your timeline and make sure that you define the duration and/or delay in terms of frames rather than seconds. In frames mode, it doesn't care about time at all - it simply counts frames. That means that if your frame rate bogs down, your tweens will last longer but they will always change the pre-determined amount on each frame.
  2. Create your tween on the next update/tick of the engine AFTER your write() function is called. You can do that using a delayedCall() that has an extremely small duration, like 0.001 and then in that function, you create your tween. Either that or call the undocumented Animation._updateRoot() method from within your

Does that help clarify things?

 

I understand how it works.

First solution is no good for me because frame rate can seriously drops and tween must finish in time.

Second solution is also no good for me beacuse I don't know when I need to call write() function, if we are looking at real scenario for my app, because there are other tweens, and I just need something like Pre-start event. Can some plugin be written?

Link to comment
Share on other sites

Hmmm...based on your question, I'm not sure you do understand how it works. Or maybe I'm missing something - what exactly would you want the plugin to do? How would it be logically possible to solve the problem? The only thing I could think of that might give you what you're looking for (kinda) is if the tween moved its start time AND adjusted its duration. But the major down side to that is that if/when you reverse() the timeline, you'd see that the tween's duration was shortened (probably not desirable).

 

It almost sounds like you want to be able to have the tween's duration be consistent AND you want the start/end times to stay consistent AND you want to be able to have huge gaps in the frame rate without there being any visual consequences. I'm pretty sure that's logically impossible. Right?

 

Again, I very well may be missing something obvious here or totally misunderstanding your question/comment.

Link to comment
Share on other sites

I have a tweens that are in timeline and I need to execute code before one tween in timeline that is going to start after some tweens.

Because that tween duration is 0.3 seconds, code that is in TweenEvent.START listener disrupts rendering on screen, so I don't need huge gap, just maybe 0.1 seconds.

So for example I need this:

TIMELINE:

1. Tween

2. Tween

3. Tween

4. Code

5. Tween

Link to comment
Share on other sites

I'm pretty sure I understand what you're asking for. I'm also pretty sure you don't understand what I'm saying or why what you're asking for is logically impossible.

 

Let's say you have three 2-second tweens that are supposed to run back-to-back in a timeline. That means it should be finished in 6 seconds. And let's say you run your code just before the last tween begins and it takes 0.3 seconds to complete. How do you want to handle that exactly? Do you want to move the tween back in time so that now the total duration of the timeline is 6.3? You said you didn't want that because the tweens must finish at the time you requested. So then do you want to move the start time of the tween forward 0.3 seconds and squish the tween into the remaining time, changing the duration to 1.7 seconds? If you do that, think about what will happen when you reverse() - there will be a gap between the 2nd and 3rd tweens.

 

See the attached graphic.

 

What would you like the plugin to do?

timing.jpg

Link to comment
Share on other sites

I'm pretty sure I understand what you're asking for. I'm also pretty sure you don't understand what I'm saying or why what you're asking for is logically impossible.

 

Let's say you have three 2-second tweens that are supposed to run back-to-back in a timeline. That means it should be finished in 6 seconds. And let's say you run your code just before the last tween begins and it takes 0.3 seconds to complete. How do you want to handle that exactly? Do you want to move the tween back in time so that now the total duration of the timeline is 6.3? You said you didn't want that because the tweens must finish at the time you requested. So then do you want to move the start time of the tween forward 0.3 seconds and squish the tween into the remaining time, changing the duration to 1.7 seconds? If you do that, think about what will happen when you reverse() - there will be a gap between the 2nd and 3rd tweens.

 

See the attached graphic.

 

What would you like the plugin to do?

 

I don't mind if 3rd tween finishes 0.1 seconds later, that's not important.

Lets make it this way. Can I insert empty tween with duration 0.1 between 2nd and 3rd that will do the code, because I tried that and rendering of 3rd tween still is choppy.

Link to comment
Share on other sites

I suspect your code is taking more than 0.1 seconds to run, then. Please post a very simple example that we can publish on our end to see the behavior. We'd be happy to help.

 

By the way, this solution that you proposed is almost identical to my #2 above, except the way I recommended would work regardless of how long your code takes to run (no need to guess 0.1 seconds)

Link to comment
Share on other sites

Can you help me with this example:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
		   xmlns:s="library://ns.adobe.com/flex/spark"
		   xmlns:mx="library://ns.adobe.com/flex/halo"
  click="starts()">

<fx:Declarations>
 <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>

<fx:Script>
 <![CDATA[
 import com.greensock.data.TweenMaxVars;
 import com.greensock.TweenMax;
 import com.greensock.events.TweenEvent;
 import com.greensock.TimelineMax;

 private var timeline:TimelineMax = new TimelineMax();

 private function starts():void
 {
  var tweenMaxVars1:TweenMaxVars = new TweenMaxVars();

  var twe1:TweenMax = new TweenMax(obj, 10, tweenMaxVars1);
  twe1.addEventListener(TweenEvent.START, write);

  var tweenMaxVars:TweenMaxVars = new TweenMaxVars();
  tweenMaxVars.x(300);

  var twe:TweenMax = new TweenMax(obj, 5, tweenMaxVars);
  timeline.append(twe1);
  timeline.append(twe);
 }

 private function write(event:TweenEvent):void
 {
  for (var counter:Number = 0; counter < 3000; counter++)
  {
trace('beforeStart')
  }
  trace("finished");

  TweenMax(event.target).progress(1);
 }
 ]]>
</fx:Script>

<s:Label id="obj" text="object"/>

</s:Application>

 

I tried to end tween twe1 with TweenMax(event.target).progress(1) so that it ends when for command ends, but that doesn't work.

How to do that?

Link to comment
Share on other sites

Setting the tween's progress wouldn't help here - that would only pick the tween up and reposition it inside its parent timeline so that the timeline's playhead is positioned accordingly.

 

If you want the timeline to jump to where that tween ends, and we know it ends at exactly 10 seconds, you could simply do this:

 

timeline.seek(10);

 

Does that help?

Link to comment
Share on other sites

Setting the tween's progress wouldn't help here - that would only pick the tween up and reposition it inside its parent timeline so that the timeline's playhead is positioned accordingly.

 

If you want the timeline to jump to where that tween ends, and we know it ends at exactly 10 seconds, you could simply do this:

 

timeline.seek(10);

 

Does that help?

 

That is working, but still if I do that, object's movement is again choppy meaning object would jump to 100 and continue to 300, even though code finishes before tween twe starts. Why?

Link to comment
Share on other sites

That has to do with the fact that the time is recorded on each ENTER_FRAME, so if you seek() after you run a bunch of code that bogs down the processor, the measurement of time between when the seek() happened and the next time the root time gets recorded is substantial. It's pretty easy to get around that, though - just do your seek() on the very next update of the engine which you could do using a delayedCall() that's very short:

 

TweenMax.delayedCall(0.001, timeline.seek, [10]);

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