Jump to content
Search Community

Interrupting a className Tween causes strange results.

bawwb 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

i was trying to use the className property on TweenLite to add and remove a css class from an element during mouse over an mouse out. using jquery, i had done something like this:

 

this.$container.hover( function( evt ) {
	TweenLite.to( _this.$content, 0.5, { className: "+=open", ease: Expo.easeInOut });
}, function( evt ) {
	TweenLite.to( _this.$content, 0.5, { className: "-=open", ease: Expo.easeInOut });
});

 

 

the problem i'm having is when i interrupt the animation with another mouse event that will cause it to remove the class before the animation is finnished, it seems the class name doesnt actually become added onto the element until after the animation is complete. so if you hover in and hover out before the animation completes, there wont be any class name to remove and the tween for removing the class will be ignored.

 

i hope this makes sense.

 

thanks for you time!

Link to comment
Share on other sites

Yeah, that's definitely a tricky situation. And your assumptions are quite accurate, you can't remove a class if it hasn't yet been applied. If we add the class before the tween is complete that would produce awkward results and basically break the expected behavior of target values only being realized when a tween is finished. 

 

The best thing to do here would be to create 1 tween and toggle between myTween.play() and my Tween.reverse() in your hover functions.

 

Or instead of using className, go the route of specifying the properties and values inside the tween.

Link to comment
Share on other sites

thanks carl.

oh well, that's a bummer, but i think i'm going to have to go that route. i'm building a html component and some tweenable properties should be changeable depending on design. so the reason i was trying to use css classes is because i was hoping to expose the property in css so whoever uses the component won't have to crack open any javascript. so the solution i think i'm going to have to go with is parsing through the document.styleSheets inside my javascript class and getting the property values of the class. that way so i can do as you suggested and tween the element using specific properties.

 

thanks for the response!

Link to comment
Share on other sites

Did you try the following? It seems like it would work well in your situation.

var openTween = TweenLite.to(_this.$content, 0.5, {
    className: "+=open", ease: Expo.easeInOut, paused:true
});
// It's not clear what _this refers to, but I'll assume it's a
// variable you've created outside of the .hover() function scope

this.$container.hover( function( evt ) {
    openTween.play();
}, function( evt ) {
    openTween.reverse();
});
  • Like 1
Link to comment
Share on other sites

As Jamie said we can't assume what _this is but each object can certainly "have its own tween".

For className tweens this is much more efficient than instantiating new tweens on the fly. 

With className tweens the engine has to loop through each property in the that class and calculate how all those properties are going to be changed each time a new tween is created.

 

Better to store them upfront.

 

A similar issue came up with someone via twitter and here is the solution I provided which illustrates how each element can be associated with a tween.

See the Pen nwJog by GreenSock (@GreenSock) on CodePen

 

I use a simple each() loop by i imagine you can apply the same play()/reverse() functionality when you build your objects for your plugin.

  • Like 1
Link to comment
Share on other sites

ah nice, thanks guys. both your solutions are similar and work as a good work around. i did end up just parsing through the document.styleSheet and finding the class properties that way. then tween the element using property values from that initial parse.

 

but i think your solutions are nice since and i will use it in the future. i like that you are only creating the single tween and re-using it. only issue i can see with it is an easeOut becomes an easeIn in reverse. which in many cases might not be desirable. but i'm sure there is a way to change the ease property on the tween right before you call reverse()?

 

thanks for the help guys.

  • Like 1
Link to comment
Share on other sites

FYI, the className overwriting routines have been rewritten in 1.9.3 which was just posted (it's not in the CDN quite yet though), and it should solve this problem now. It was kinda tricky because it needs to track which inline styles are className-related and remove them appropriately at the end of the tween (or beginning if you rewind all the way). And if there's a className tween that's in-progress (thus inline styles present), the new one must take over seamlessly and manage those inline styles appropriately. 1.9.3 should be pretty bullet-proof in that regard now. I tested it while rolling my mouse over/out very quickly and it never broke. Feel free to give it a shot. 

 

http://www.greensock.com/?download=GSAP-JS

Link to comment
Share on other sites

holy crap, wow.

this is great to hear!

i understood the challenge of this, and i was rackin my own brain on thinking of a good solution and not a work around, but you already nailed it in your next rev.

 

seriously, you guys are on point, it's amazing. ;)

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