Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Rodrigo

Invalidate specific property

Recommended Posts

Hi,

 

Is possible to invalidate just a single property?.

 

I have a timeline and after the first execution it stores the initialization data for future play. The thing is that one of the tweens nested in the timeline could change, because the height property of the target element changes. But if the timeline plays again the height is the original value not the changed one, which causes to look bad.

 

So far I've sorted out like this:

tl1 = new TimelineMax({paused:true, onComplete:comp});

tl1
     .set(div1, {left:50, height:100})
     .to(div1, 1, {left:250})
     .to(div1, 1, {height:200});

By putting the set tween it takes the values to what I want, whether is the original value or the changed one. But it would be great to clear just that value.

 

Cheers,

Rodrigo.

Link to post
Share on other sites

You can't invalidate only one individual value in a tween, no, but you could just isolate that part in a DIFFERENT tween so that you can invalidate() it without affecting the other properties. In other words, use one tween for the height, and another tween for the rest of the properties. See what I mean? 

Link to post
Share on other sites

Hi Jack, thanks for the answer and sorry for not coming back to you before.

 

The thing is I tried what you said but it doesn't works, but filling the timeline with pauses and console.log's brought to me the fact that the previous tween of the timeline is the one keeping the old value, and therefore invalidating that tween made it work.

 

in the following fiddles do as follows:

  1. Play the timeline.
  2. Change Height and play the timeline.
  3. Reset the fiddle to clear all init data
  4. Change Height and play the timeline.
  5. Restore Height and play the timeline.

As you see invalidating the previous tween allows playing the timeline with the changed property.

 

http://jsfiddle.net/rhernando/KaerE/ (Invalidate the changed tween)

 

http://jsfiddle.net/rhernando/KaerE/1/ (Invalidate the previous tween)

 

Also I ended up having quite a lot of problems by adding the set tween at the beginning of the timeline so that turned to be a bad approach.

 

Cheers,

Rodrigo.

Link to post
Share on other sites

It looks like things are behaving exactly as they should, but I wonder if it would help if I clarified how tweens work under the hood...

 

When a tween renders for the first time, it records the starting and ending values so that it can interpolate between those during the course of the tween. If the engine had to keep going out to get the starting value again and again (like "what's the height now? And now? And now?"), it would significantly degrade performance. So you had 2 tweens that were affecting the div's height. That first one recorded the starting value as 100 and the ending value as 20. Then your 2nd tween made it go from 20 to 100 (and of course you altered that 100 value to be 300 when clicking the button). So when the timeline rewound, it also rewound that first tween which would make the height go back to 100 (the value it recorded at the beginning). 

 

Make more sense now? 

 

I didn't quite follow what you meant about the set() calls at the beginning of the timeline. Remember, once a tween has rendered once and recorded its values, the only way you can clear out those values is to invalidate() the tween(s). 

  • Like 3
Link to post
Share on other sites

Hi Jack,

 

Thanks for the clarification and help to understand how things works.

 

What I meant with the set calls is that I thought that by adding a set call at the beginning of the timeline I'd force the timeline to set to properties of the element when the timeline started, the point is that it also created a problem with other properties at the start of the timeline.

 

Cheers,

Rodrigo.

Link to post
Share on other sites

Yep, a set() would indeed set the values at the beginning, but that doesn't mean it would invalidate all tweens thereafter if you alter that set() call later, after the subsequent tweens had instantiated and recorded their start/end values. In other words:

 

tl.set(e, {x:100}); //sets x to 100
tl.to(e, 1, {x:200}); //tweens x from 100 to 200
tl.seek(1); //jump to the end (e.x is now 200)
tl.set(e, {x:500}, 0); //this does NOT make the to() tween start at 500 and go to 200 because that tween has already recorded its start as 100 when it ran!

While this may seem unintuitive in your particular situation, it's actually the most intuitive behavior in most situations - when someone rewinds a timeline or tween, they want the beginning values remembered/reverted. If a new tween (or set()) gets retroactively inserted into a timeline, they don't want it to then change the other tweens that already ran. But we do recognize that sometimes they'd prefer that the beginning values get flushed which is why we provide the invalidate() method. 

 

You can think of a set() as just a zero-duration tween (because it is). It records starting/ending values just like any other tween so that if you move the playhead before or after that spot, it'll render things correctly.

  • Like 2
Link to post
Share on other sites

Yep, a set() would indeed set the values at the beginning, but that doesn't mean it would invalidate all tweens thereafter if you alter that set() call later, after the subsequent tweens had instantiated and recorded their start/end values.

 

Right on Jack, that was my problem, I thought about the set call in the wrong way but I see know that is just a tween as any other, thus causing unwanted behavior but just because of how I used them.

 

At the end invalidating the previous tween was the perfect solution.

 

Thanks a lot for the explanations and patience 8-)

 

Cheers,

Rodrigo.

Link to post
Share on other sites

Hi,

 

I have the need to reuse the timeline similar to the example discussed above. Please check the pseudo code here: http://jsfiddle.net/shiyaz/khz8E/1/

 

Please click the button twice to see the problem. I did try to invalidate, but the styles are not reset to initial condition. On clicking the button each time, it should behave like 'restart'. Kindly help.

 

Warm Regards,

Shiyaz

Link to post
Share on other sites

Hi Shiyaz and welcome to the Greensock forums.

 

It seems to me like an overwrite issue, but I'm not sure. The thing is that in the animateIn function you add a from instance for scale and opacity and then in the animate out you tween the scale of the element. Since you're creating two instances that affect the same element and the same property the last one created takes priority over the previous one. What strikes me as odd is the fact that you're positioning the instances absolutely, so the scale down shouldn't happen on the moment the fade in, but later. Perhaps it's an expected behaviour but I'm not aware of all the code optimizations of the engine in order to give you a solid answer in that matter. Carl or Jack are more suited for that.

 

What solves the issue is to remove the scale:1 in the animateIn property and, since you're using a from instance, remove the scale from the element's inline style using clearProps, like this.
 

function animateIn(el)
{
    TweenLite.set(el, {clearProps:'scale'});

    var tl = new TimelineLite({
        paused: true
    }).from(el, 1, {
        opacity: 0
    });
    return tl;
}

Like that if the element's scale was modified before it'll be removed and the whole animation works as the first run all the time, you can see it here:

 

http://jsfiddle.net/khz8E/2/

 

Rodrigo.

  • Like 1
Link to post
Share on other sites

This isn't an overwriting issue - it's just a logic flaw in your code. Let me explain...

 

You're calling anim() each time you click that button, and you're re-creating the entire timeline (and all the animations), but you're starting at different initial values. Let's focus on the green square. First, it starts at a normal scale (1). So when you do your from() tween, it uses that current value as the end value, and animates from 0 to 1. Great. Then at the end of the timeline, you animate its scale back to 0. So now, when you re-create your entire timeline again (when the button is pressed the 2nd time), scale is at 0, so the from() tween animates from 0 to...0 (because that's the current value)! It's doing exactly what it's supposed to do. 

 

There are many ways to restructure your code to solve this; here's one:

http://jsfiddle.net/2Frhn/1/

 

If the timeline already exists, just restart() it. Otherwise, create it. That slightly improves performance too, since you're just reusing the same timeline over and over instead of creating new ones each click. 

 

You could also just manually reset the scale (or whatever other values) before creating the tweens/timeline instead. Or use a fromTo() tween so that you can define both the beginning and ending values.

  • Like 4
Link to post
Share on other sites

Thank you Rodrigo, your solution worked for me. The key was to clear the styles in the animate in function and use opacity instead of autoAlpha.

 

Thank you Jack, for pointing out the logical issues and your detailed clarifications. The example earlier didn't have the entire use case. I've updated the fiddle here: http://jsfiddle.net/shiyaz/khz8E/3/

 

The timeline could not be reused since i had to overwrite the TL for other animations. The reason for this is that all animations are controlled with the help of a common controller - hence the need overwrite the object.

 

Once again, thank you both. Did i tell you?... this is an awesome library keep up the fantastic work.

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

×