Jump to content
Search Community

Quick tip which might help others head scratching !

omoptical test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

So, this one had me going for about 5 hours yesterday.  Maybe it was a late night, but in case anyone else runs into the same problem I thought I'd post about it.

 

The story so far :: I've been programming a game for mobiles using kinetic & the lite greensock libraries.  In order to keep the main animation loop nice and tight the plan was to generate all of the tweens during the initialisation phase, store them in an array and call them by adding them to a timelinelite instance depending on what phase the game was in.

 

The problem :: every time I created a new tween it ran ! Not so handy when trying to pre-compute them.  I looked at test code I had written when coming up with a strategy and that code was running fine.  I could create the tweens, store them in variables, and they'd be ready.  There seemed no difference in the code, but the results were different.

 

The (eventual) solution :: It turned out to be a scoping thing.  Because most of the functions for the game are in a different js file, and I was creating the main work-horse timelinelite instance in the main page when adding the tweens in the function stored in the js file, I'm guessing the library thought "hmm, I can't see a TLL object, I better run these right away"

 

So it was a really easy fix in the end, I just declared a paused dummy TLL object in the function which sets up the tween presets, add the tweens to this a few lines of code after setting them up and all is well. They're ready for use when needed.

 

It's probably just a case of me not RTFM correctly, but I couldnt' see any info about it. 

 

Hope this nugget helps someone avoid the head scratching and beard pulling I went through !

 

Bests

 

om

Link to comment
Share on other sites

Om,

 

You can pass a paused parameter when you create a timeline.

 

tl = new TimelineLite({paused:true});

 

timelines begin to play by default unless otherwise stated.

 

From the docs:

 

 

paused : Boolean - If true, the timeline will pause itself immediately upon creation (by default, timelines automatically begin playing immediately). If you plan to create a TimelineLite and then populate it later (after one or more frames elapse), it is typically best to set paused:true and then play() after you populate it.

  • Like 2
Link to comment
Share on other sites

I'm really confused by this behaviour, it goes against everything I understand about the system. Just to clarify, do you mean that something like this:

var foo = new TimelineLite({ paused:true });
foo.to(bar, 1, { left: 100 });
is actually playing? I can't imagine any reason that it could unless you remove the tweens from the timeline i.e.

var foo = new TimelineLite({ paused:true });

// not added to the foo timeline, will autoplay
TweenLite.to(bar, 1, { left: 100 });

// not added to the foo timeline, but will be paused
var baz = TweenLite.to(bar, 1, { left: 100, paused: true });
Could you provide a bit more information about this (a code sample could be useful) since if it really is behaving as you describe, it could possibly be a bug in the engine Jack might like to fix.
Link to comment
Share on other sites

sure, in the interests of greater happiness, though this is likely to bring some horrible coding 'techniques' to light.

 

in, say "main.html" which does setting timeout and initialising the graphics I declared a

 

tll = new TimelineLite({paused:true, onComplete:gameLogic});

and

someTweenArr = [];

 

then in "functions.js" I have a function which is setting up all of the tweens in advance to keep them out of the main cycle

 

function setUpTweens(){

...

var tweenNo126 = new TweenLite(tileImages[cur], ant6, {kinetic:{y:"+=" + threeTilelHeight}, ease:Elastic.easeOut, easeParams:[easeP1, easeP2]});

someTweenArr.push(tweenNo126)

....

}

 

In this case the tweens start running as soon as they're created.

 

The strange (well, it seemed a bit odd to me anyway, but it's been a long night...) solution was to add a bogus

 

var bogusTl = new TimelineLite({paused:true});

 

to the top of the function and after minting each new TweenLite

 

do a

 

bogusTl.add(tweenNo126);

 

So the whole function becomes

 

function setUpTweens(){

 

var bogusTl = new TimelineLite({paused:true});

 

var tweenNo126 = new TweenLite(tileImages[cur], ant6, {kinetic:{y:"+=" + threeTilelHeight}, ease:Elastic.easeOut, easeParams:[easeP1, easeP2]});

 

bogusTl.add(tweenNo126);

 

someTweenArr.push(tweenNo126);

 

}

 

It seems to me like the tweens look around for a timeline in their local scope and if they can't find one decide maybe they're on their own and free to start doing their thing.

 

But I didn't actually realise that tweens could be started in a paused state, so that might have saved me a lot of grief :P

Edited by omoptical
Link to comment
Share on other sites

But I didn't actually realise that tweens could be started in a paused state, so that might have saved me a lot of grief

 

 

Yeah, I think that is the cause of the confusion.

 

Just like timelines, tweens will play immediately upon creation. This is a great convenience for the majority of the use cases of tweens. We wouldn't want to force our users to invoke an additional play() on each tween they create. For the cases where you don't want your tweens to start playing immediately you can just create them in a paused state (as you have learned).

 

And to be clear, tweens don't look to see if they are in paused timeline, they start playing naturally totally unaware of where they are. If they happen to be added to a timeline that is paused, then yes, the paused state of the timeline will prevent them from playing. 

 

To start a tween in a paused state...

 

use paused:true in the constructor

var t = TweenLite.to(elem, 1, {x:100, paused:true});

OR call pause() on it

var t = TweenLite.to(elem, 1, {x:100})
t.pause();

even chain the pause() call

var t = TweenLite.to(elem, 1, {x:100}).pause();

or if you like typing more than necessary :) use paused(true)

var t = TweenLite.to(elem, 1, {x:100}).paused(true);
  • Like 1
Link to comment
Share on other sites

Ah thanks, I think I understand the situation now. This is all actually expected behaviour; I think there's just a little confusion to how tweens work inside and outside of timelines.

 

When you create a tween:

var foo = TweenLite.to(bar, 1, { left: 100 }); // or, new TweenLite(bar, 1, { left: 100 });

this does not look for any of your own created timelines, in the current scope or otherwise, to be added to. It is added to GSAP's internal 'global' timeline, but for simplicity sake you can just consider this tween standalone, without any parent timeline. It starts playing straight away, and will render on the next render frame (if duration === 0, or immediateRender:true is set, it renders immediately).

 

When you add a tween to your own timeline, its playhead becomes synced with its position in that timeline. This is why the tween appears 'paused' if the timeline itself is paused. The tween still isn't technically paused, but it doesn't render because its parent is paused, and hence its own playhead isn't moving.

 

In summary: if you don't actually add the tween to a timeline yourself, it won't look for a timeline to live in, and will just play as a standalone tween.

  • Like 2
Link to comment
Share on other sites

Ahh, thanks for the explanation, that's interesting stuff.

 

So, it's a frame based thing :: If a tween gets added to a paused parent timeline within 16ms (mes o menos) of being instantiated, it signs up to that queue.  Otherwise, if the frame passes without it being added to timeline, it grabs the next frame to start dancing in (unless it's paused already itself) ?

 

And... please don't take any of this as a grumble - really, I haven't enjoyed coding this much in years - just trying to get my head around it.  About a week in, and I'm sure most of the code I write now will look terrible after a few months of picking up decent patterns and techniques.

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