Jump to content
Search Community

Understanding "call" behaviour

kalreg test
Moderator Tag

Go to solution Solved by kalreg,

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

Hi guys. Probably Carl seeing my new post is starting to shake but where can i go and ask if not here? :)

 

I am still struggling with .call and .add but cant figure out how to use it correctly.

 

I've attached codepen for you to understand a problem.

 

Here is short description. If i press "m" call of obj.myFunc on mainAnimation should be started which should set color of text in body to red after 2 seconds.

 

That never happens. If you check more closely whole obj.myFunc is not even called: Now, if i change:

mainAnimation.call(obj.myFunc, ["abcd"], "+=2")

to 

mainAnimation.call(obj.myFunc(), ["abcd"], "+=2")
myFunc is called, but without any parameter and without 2 second delay.

 

Now, if i change it to:

mainAnimation.call(obj.myFunc("abcd"), [], "+=2")
myFunc is called with parameter ("abcd"), but still - no 2 second delay.
 
What am i missing? 
I intend to add a call of function to mainAnimation with some delay.
Also Carl said that using .call(func) is good instead of .call(func()) which is bad. Why is that bad? What is the difference? 
 
 

Kalreg

 

 

See the Pen VpyLER?editors=0010 by kalreg (@kalreg) on CodePen

Link to comment
Share on other sites

Looks like you were missing a parameter. Specifically, you put "+=2" for the scope (but I'm sure you meant that as the position parameter). 

//BAD:
mainAnimation.call(obj.myFunc, ["abcde"], "+=2")

//GOOD:
mainAnimation.call(obj.myFunc, ["abcde"], obj, "+=2")

The reason you thought that obj.myFunc() worked (instead of obj.myFunc) is because the "()" tells the browser to immediately call that function. It invokes it. That's not a reference to the function itself. In other words:

console.log(obj.myFunc); //the function itself
console.log(obj.myFunc()); //calls the function and logs whatever the function returns.

Also, I'm curious why you're using a call() in a timeline anyway. It's fine - nothing "wrong" with it, but if your goal is to simply call something after a certain amount of delay (but you don't need it embedded into some sort of sequence that can be played backwards/forwards, timeScaled, etc.), it's simpler to just call TweenLite.delayedCall(2, yourFunc)

 

What's a little weird about your demo is the fact that you create a timeline initially and by default it starts playing but you don't actually add anything to it until later (like when you hit the "m" key). By that time, the timeline's natural playhead would be much further down the timeline, but you're actually placing your call() 2 seconds from the end (which is the same as the beginning since it's empty). Thus you may get results that you weren't expecting. 

 

Think of it like if you started a stopwatch now....and then 3 minutes later you said "I want to make something happen when my stopwatch says 2 seconds"...but your stopwatch is at 180 seconds already, so you're now talking about something in the past. It's easily solvable by doing a restart() of your timeline or something...so it's not necessarily "wrong" but I figured I'd mention it because it looked odd to me. 

 

Does that clear things up at all?

  • Like 2
Link to comment
Share on other sites

It clears a little, but unfortunatelly doesnt solve my problem. First of all thank you PointC for "this" usage, and Jack for so complete explanation. 

 

Jack: I use mainAnimation as a controller that is telling me if any animation is in progress. Because i can animate many divs from different kinds and purposes i need to know if any animation is in progress. So i add any tween to mainAnimation. If for example button is currently animated, and user clicks different button i do not want to play second button animation immidiately, but i want it go to queue. When first button finishes animation, the second will be animated since i added all animation tweens to mainAnimation. 

I didnt know that mainAnimation is in progress all the time - i thought if there is nothing added (or all animations have ended) it stops untill next tween is added.

 

Anyways what i want to achieve is (i try to simplify everything as much as possible):

 

1. add tweens on click event attached to button

2. if user clicks button check conditions:

    a/ if none of the buttons is currently animated - start animating it by adding tweens of button to mainAnimation

    b/ if any button (or any other entity) is currently animated (which means that it is added to mainAnimation), add currently clicked entity tweening to end of queue in mainAnimation

 

Problems:

1. there may be different objects animated - divs, buttons, different classes, it is hard to find something in common for isActive() usage;

2. tweens, are not only animations, but also normal code like defining variables depending on what is going on, creating dom objects, so if i add something to the end of mainAnimation i expect all the code will be executed in moment of starting the animation (when all other animation finishes). So any variable/dom check refers to the moment that certain tween is being played, not checked in moment of adding tween to mainAnimation.

 

I updated codepen: 

See the Pen VpyLER?editors=0011 by kalreg (@kalreg) on CodePen

 

What i do is:

1. i press key "m" which calls tripple times myFunc with red, later green and later blue parameter

2. right after pressing "m" i press "n" which calls myFunc3.

 

What i expect:

1. myFunc is called 3 times with different color. Because each myFunc also adds call of myFunc2 i expect that it would add MyFunc("red") to mainAnimation, then myFunc2, then("green"), and myFunc2 again and so on. 

2. because myFunc3 is called after myFunc and myFunc2 it should be added at the end of mainAnimation so expected behaviour should be:

 

Text change:

from white to red
from black to orange
from orange to green
from black to orange
from black to blue
from blue to magenta
 
and console output should be:

A:
1
1
1
B:
2
2
2
3
As you can see on codepen both output and color behaviour is completely different.
Is that possible to achieve what i expect?
 

Thank you!

K.

Link to comment
Share on other sites

Yes, i do want to queue tweens, but also callbacks. I've been thinking about storing in array tweens or animated dom objects and removing them when animation finishes, but i hoped that gsap has some more simple solutions to queue both callbacks and tweens in one chain. 

 

Here is next pen for you guys:

 

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

 

I want to have queued:

-- first call of obj.myFunc

change color of text to red (call myFunc) and then

change color of text to red (call myFunc2) and then

change color of text to red (call myFunc3) and then

-- second call of obj.myFunc

change color of text to red (call myFunc) and then

change color of text to red (call myFunc2) and then

change color of text to red (call myFunc3) and then

-- first call of obj.myFunc4
change color of text to magenta

 

All callbacks are queued in order i started them honouring that myFunc calls myFunc2, it calls myFunc3 and when it finishes - call again myFunc and so on... Is that even possible? I am sitting with it for 24hours now and no luck:(

Link to comment
Share on other sites

That's what a timeline is for  - chaining tweens and callbacks. That would certainly work perfectly if you were constructing the timeline and then playing it. But you're trying to add tweens (based on user interaction which may or may not happen) to a timeline that is already running. If I correctly understand what you're trying to do, I don't think you're going to find a simple built-in solution to make that work as you'd like.  

 

You're creating tweens dynamically based on user interaction and then want them to wait for the prior tween to finish, right? I think your best solution is something like Blake is doing in that demo I listed in Post#5. You'd need to push the newly created tweens into an array and have some sort of onComplete callback go check if a new tween is in there.

 

Happy tweening.

:)

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