Jump to content
Search Community

Update Variable for speed of tween

Vince test
Moderator Tag

Recommended Posts

Hello again

 

My current issue is probably quite a simple one, however after various research on here I have not yet found the solution. Any help would be greatly appreciated.

 

I calculate the speed of a tween based on a start and end location of an object when tweening, however the variable which holds the value of this speed calculation doesn't update the tween before it runs.

myTimeline.append(TweenMax.to(mc, speed_x, {onInit:calcSpeedx, onInitParams:[location01_x, location02_x], x:location02_x, delay:animDelay, ease:animEase}));

function calcSpeedx(startLocation_x:Number, endLocation_x:Number):void
{
speed_x = Math.abs((endLocation_x - startLocation_x) / pixelsPerSecond_x);
}

Is there a simple way of using a variable for the speed of a tween, calculated from within that same tween?

 

Many thanks for your help

 

Vince

Link to comment
Share on other sites

Are you saying you want to create a tween but you have no idea how long it should last until later? May I ask why you need to create it ahead of time instead of just creating it when you have the data you need? It seems like there may be an architecture issue, but maybe not. 

 

Are you using the old v11 stuff or have you upgraded to v12 yet? I'd definitely recommend v12. 

 

Here's one option:

myTimeline.call(createTweenX, [mc, location01_x, location02_x, "{self}"], "+=" + animDelay);
function createTweenX(mc:DisplayObject, start:Number, end:Number, callback:TweenLite):void {
    var speed_x:Number Math.abs((end - start) / pixelsPerSecond_x);
    myTimeline.to(mc, speed_x, {x:end, ease:animEase}, callback.startTime());
    callback.kill(); //just removes the callback so that if the timeline runs again, it doesn't get called (we've already created the tween)
}

All I'm doing there is adding a callback to the timeline that, at that time, calls a function that does all the math and creates the tween and drops it into the timeline at the exact same spot as the callback. 

 

Here's another option:

var tween:TweenLite = TweenLite.to(mc, speed_x, {startAt:{onComplete:calcSpeedx, onCompleteParams:[location01_x, location02_x]}, x:location02_x, delay:animDelay, ease:animEase});
myTimeline.add(tween);
function calcSpeedx(startLocation_x:Number, endLocation_x:Number):void {
    tween.duration( Math.abs((endLocation_x - startLocation_x) / pixelsPerSecond_x) );
}

That just uses a startAt object with an onComplete/onCompleteParams because the startAt is just a vars object that gets fed to a tween BEFORE the parent tween inits, so that onComplete happens before any values are recorded. That way, it'll only run once regardless of how many times that parent tween plays forward/backward. And that callback just adjusts the duration according to the variables you've got. 

 

There are several other ways to do this, but these are a few that came to mind initially. I hope it's helpful. But again, I suspect there might be an architecture issue that, when resolved, would make your code even more concise and robust. 

 

Happy tweening!

  • Like 1
Link to comment
Share on other sites

Thanks for the great responses, you maybe right about the structure or architectural setup.

 

Currently using version 11, but only because I have a very long animation I don't want to have to go through and update with new code yet.

 

I did come up with a solution by applying my function in the tween length value instead of using a variable:

myTimeline.append(TweenMax.to(mc, calcSpeedx(location01_x, location02_x), {x:location02_x, delay:animDelay, ease:animEase}));
myTimeline.append(TweenMax.to(mc, calcSpeedx(location02_x, location03_x), {x:location03_x, delay:animDelay, ease:animEase}));

function calcSpeedx(startLocation_x, endLocation_x:Number):Number
{
	return Math.abs((endLocation_x - startLocation_x) / speed_x);
}
 

This works fine, however I notice it does go through all the appended tweens simultaneously when creating the timeline, which I assume logically is correct. I was ideally hoping it would calculate the length of the tween, play it and move onto the next tween in sequence.

 

As I'm fairly new to this, I'm not sure if its the right way or ideal way of doing this.

 

Thanks again for your suggestions, I'll look at those next and see if they are a better solution.

Link to comment
Share on other sites

Yes, think of the code you've got there as "setup" code, so you're setting up a bunch of tweens that will then start running on the very next frame/tick. The beautiful thing about this is it allows you to run logic on the entire sequence (like figure out the total duration or seek() to a certain spot, both of which would be impossible if it behaved the way you were originally expecting, like playing an entire tween, then building the next one, etc.). It also ensures that everything is synchronized and perfectly timed. If you wait until one tween is done before you even build the next one, you can end up with gaps inbetween, depending on system performance and several other factors. Granted, it'd probably be almost imperceptible, but if you're doing 500 sequenced tweens and there's a 1/60th of a second gap introduced between each one, that adds up to 8.3 seconds over the course of the whole thing. 

 

Is there a reason you're using a timeline for this? Not that it's bad - I just need to know if you need to be able to control the entire sequence as a whole later on or seek() to certain spots, run in reverse, etc. That's a key piece of data in determining how you should build this.

 

If you don't need any of that control and you just want to sequence these calls and actually have the next one created after the previous one is done, you could easily accomplish that using an onComplete for each tween. Kinda like this:

TweenMax.to(mc, calcSpeedx(location01_x, location02_x), {x:location02_x, delay:animDelay, ease:animEase, onComplete:next});
function next() {
    TweenMax.to(mc, calcSpeedx(location02_x, location03_x), {x:location03_x, delay:animDelay, ease:animEase});
}

Of course you could architect things however you want, but the concept is to just use an onComplete to trigger the next thing. 

 

I personally think that's a less tidy way of building it, and I favor using a TimelineLite unless you need to have tweens built/calculated at different times. And actually, even if that's the case, I gave you a way earlier to do that within the context of a timeline too. I hope I'm not adding to the confusion here by giving you a lot of options :)

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