jesper.landberg

How to use doneFn with tweenmax in angular 1.4+?

Recommended Posts

Hi,

 

I'm trying to create enter and leave animations with TweenMax and angular 1.4+.

 

I have this code:

 




.animation('.page', [function(){

return {
enter: function(element, doneFn){
TweenMax.from(element, 1, { css: { transform: "scale(0.8)", opacity: 0 }, force3D: "auto" });
},
leave: function(element, doneFn){
TweenMax.to(element, 1, { css: { transform: "scale(1.1)", opacity: 0 }, force3D: "auto" });
}
};

}])


 


The animations are working but the thing is the pages get stacked, since I don't tell angular when the animation is done. You are supposed to use "doneFn" for this but I don't know how to implement that in the code.

 


Share this post


Link to post
Share on other sites


.animation('.page', [function(){

 

return {

enter: function(element, doneFn){

TweenMax.from(element, 1, { scale: 0.8, autoAlpha: 0, onComplete: doneFn });

},

leave: function(element, doneFn){

TweenMax.to(element, 1, { scale: 1.1, autoAlpha: 0, onComplete: doneFn });

}

};

 

}])

 

  • Like 4

Share this post


Link to post
Share on other sites

Hijacking this a bit but what happens if I have a situation where I'm using the addClass/removeClass and a timeline.  I'm not sure if this is the right approach or not as the class could be applied and removed to an element quite rapidly, before the previous animation has completed potentially.  I'm seeing growing memory usage which I think it might be doing this wrong as I have the timeline variable outside the addClass/removeClass, which feels a bit wrong.  I have a feeling that timelines are getting orphaned but still running their animation loops.

.animation('.sample', ['$animate', function ($animate) {
        
        var tl;
        
        return {
            addClass: function (element, className, doneFn) {
                                
                var images = element[0].getElementsByTagName('img');
                
                tl = new TimelineMax({ repeat: -1 });
                
                tl.staggerTo(images, 0.2, { y: -40 }, 0.2);
                
                doneFn();
            },
            removeClass: function (element, className, doneFn) {
                
                if (tl)
                    tl.clear();
                
                doneFn();
            }
        }
    }])

Share this post


Link to post
Share on other sites

Hi @deejbee,

 

That's a very good question. Understanding how the done function works confuses a lot of people. Angular has no concept of your animation, so the done function lets Angular know the animation has completed. This is particularly important if something is scheduled to happen after the animation has completed, like removing the element from the DOM. If you have an animation for removing an element, and you immediately call done, the animation won't happen because Angular will immediately remove the element.

 

For adding and removing classes, this is less of an issue. But for structural changes, like adding or removing elements, it's pretty important for the done function to be called at the right time.

 

I can help you work out issues for your animation, but I need more context about what you are doing. For example, how is the class being added? Is it being added by Angular using something like ng-class, or are you adding it manually using the $animate service? How many elements are using this animation? I might have a better way to do this. If you could make a demo, it would be really helpful.

 

As far as your timelines being orphaned, again, I need more context so please provide a demo. Here's an important little tidbit about Angular. Everything is a singleton except for controllers. A singleton means there is only one instance. So putting the timeline before the return statement is the correct way to declare something that you want to be available to all the animations for that module. However, to do that with a timeline, you need to make sure that there's only 1 animation using that timeline at a time, otherwise you're going to have some unexpected behavior going on.

  • Like 3

Share this post


Link to post
Share on other sites

Just to add my two cents and to add to Blakes great advice! I notice the values for your addClass tween are static, meaning your not passing any values to your tweens. And your creating a new timeline on every addClass call. It will probably be better to create your timeline and tweens outside that addClass, and then just simple play() the timeline. And then on removeClass reverse() your timeline. This way your not creating multiple timeline and tween instances on every addClass and removeClass. Which is what Blake advised above about making sure there's only 1 animation using that timeline.

 

I am not very familiar with Angular, but i'm sure Blake can solve your issue with using GSAP and Angular with ease!

 

:)

  • Like 1

Share this post


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.