Jump to content
GreenSock

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

isActive() returns false even if animation is currently playing

Recommended Posts

Hi guys,

 

I am still struggling with queueing callbacks and next (nested) timelines however strange problem occured to me.

 

Please check my codepen:

On line 20 you have isActive() check, however if animation is being played (press m to start animation, and press it again to queue next part, during first play) you can see that the result of check is always false. Why is that? I tried with some solution with export root, however without any luck. How to get true when animation is being played?

 

There is also different problem. On line 28 there is tl.play() command. I added it because my animation didnt even started without it, i do not know why. I would expect that after adding lines 24 and 27 it would automatically run, but it didnt. Why didnt it run and is that really necessery to play it via tl.play? What is interesting to me, if i unhash line 25 (which is "tl.to" command) it will run without tl.play(), but i need to use tl.add/call instead of tl.to - i need real callbacks instead of animation.

 

I guess both problems are connected - after unhashing tl.to isActive returns true -  but i leave it to you - ppl with wisdom. Hope to get any suggestions from you.

 

EDIT: i commented whole pen for you guys to make it more clear. Hope it helps

See the Pen OpzqNM?editors=1111 by kalreg (@kalreg) on CodePen

Link to post
Share on other sites

Thanks for adding the comments. Although you described that you weren't getting the desired results with isActive() it would be a big help to have some information on what the desired "visual" behavior of the demo is. It took me quite a while to unravel the recursive function calls, conditional logic and array manipulation to assess that you want the green box to turn magenta after it stopped moving. 

 

I added a few console.log()s so you can see that you were only adding functions to the timeline, not the timelines those functions returned when called.

Please see the demo here and follow the instructions:

 

http://codepen.io/GreenSock/pen/dvJxGM?editors=0010

 

After setting fixed = true on line 2 is that the result you want?

  • Like 3
Link to post
Share on other sites

I'm also wondering what you're trying to do. In the post that PointC linked to, I mentioned promises, which might be a better option. 

 

A promise is a proxy for something in the future, and will let you compose stuff just like you described in this post. Look at how many times you used the word "then". Now look at the syntax to run a chain of promises.

 

putYourRightFootIn()
  .then(putYourRightFootOut)
  .then(putYourRightFootIn)  
  .then(shakeItAllAbout);

 

You can add as many thens as you want. Whatever you return in a function will be passed into the next then call.

 

Promise.resolve("Hello")
  .then(function(msg) {
    console.log(msg); // Hello
    return "World";
  })
  .then(function(msg) {
    console.log(msg); // World
  })

 

So how does it know when an animation has finished? It doesn't. If you add an animation to a then function, it will execute and go on to the next then. To make it wait until an animation is complete, you need to wrap it an a promise. When the animation is complete, call resolve, and it can move onto the next then.

 

Promise.resolve()
  .then(function() {
    return new Promise(function(resolve) {
      TweenLite.to("#box1", 2, { x: 400, onComplete: resolve });
    });
  })
  .then(function() {
    return new Promise(function(resolve) {
      TweenLite.to("#box1", 2, { x: 400, onComplete: resolve });
    });
  })

 

Here's a demo showing the difference between running animations with and without a promise.

 

 

 

You could also create a function to wrap an animation for you. If you've done animations in Angular, React, or Vue, you might be familiar with creating animations that look like this. Once you call done, the element is removed from the DOM.

 

function leave(element, done) {
  TweenLite.to(element, 1.5, { x: 400, autoAlpha: 0, scale: 0.5, onComplete: done });
}

 

And here's how do that using promises. This can make your animation code very modular.

 

 

I know a lot of people aren't familiar with promises, but they are really helpful once you get the hang of them. All modern browsers support them, and there are of tons of polyfills for IE and older browsers.

 

http://caniuse.com/#feat=promises

 

To polyfill older browsers, just include this script. It uses polyfill.io

<script src="https://cdn.polyfill.io/v2/polyfill.js?features=Promise"></script>

 

 

  • Like 7
Link to post
Share on other sites

Since I wrote all that, I might as well show how working with promises is much easier using async and await. They are part of the ES7 version of JavaScript, but you can use them now if you're using TypeScript or Babel. I know TypeScript can compile it all the way down to be compatible with IE6.

 

Adding "aysnc" before a function will make it a promise. And adding "await" before an expression inside an async function will pause the function. So instead of creating a huge chain of then calls, you can pause a function like this.

 

async function playAnimations() { 
    
  await animation1();
  await animation2();
  await animation3();
  await animation4();
}

 

And here's a working version of that.

 

See the Pen dvdoze?editors=0010 by osublake (@osublake) on CodePen

 

  • Like 6
Link to post
Share on other sites

Excellent explanation Blake. :)

 

I was just reading about promises last night to learn a bit more as I have no experience with them.

 

So, here's another Blake answer going into my forum favorite file. Thank you.

  • Like 2
Link to post
Share on other sites

First of all i want to thank you a lot for both - solutions and explanations. It shed o lot of light for not only gsap, but also other javascript functions.

 

@Carl: Your solution works perfectly fine. And all that because fn.callback() instead of fn.callback. I was so close :). Sorry was not clarifying what is desired result, next time i will describe it more clearly. Thank you so much, also fo private message.

 

@OSUBlake: I like your solution with promises very... promising. I tried to adapt your first codepen to my project, however thinking in promises way is quite new for me. Anyways i think that such a solution is perfect one for queueing like mine. I digged a little bit but the thing that blocked me is dynamic chaining. What do i mean.

In your example you have

promise
  .then ({ some code })
  .then ({ some code })
  .then ({ some code })
  .then ({ some code })
 
It works perfectly clear to me, however it is a programmer who decides how many "thens" there is (in that case - four), not a user or any variable. Is there a way to - for example - if i click button twice add second "then" (second promise?) to first one? And if there is third click in a meantime - the third promise will be added? I am talking about about promises added to promises. I hope you know what i mean. I know that it is not a gsap question, however i count for any advice or links to pens/tutorials
 
@PointC: i also known that something like promises is there somewhere but didnt know how or when to use it. thanks to blake my studpidity is a little bit smaller :)

 

 

Once again - you all of you are like my personal heroes.. with green cape :)

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

×