Jump to content
Search Community

Callback within a Callback? First timeline attempt!

smallio 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

Hello fellow tweeners!

 

Hit a brick wall here even though I feel like I've done the hard part. I've been referring to documentation for hours trying to solve this.

 

I'm trying to fire my page loading counter after it fades in, via the tween that does so. Everything is setup & neatly organised/labeled but I'm just butchering the last part lol. The three parts I'm using are marked with lots of asterisks & notes explaining what I'm trying to do. The load counter needs to be nested inside the "onComplete" callback which is already being fired by my tween (console log works)... just not able to get the countdown in. *sigh*

 

Any help would be massively, massively appreciated. Loving the library & community equally!

 

Cheers,

Smallio

 

Sorry for the newbie question <3

 

See the Pen ppYOLm?editors=0010 by smallio (@smallio) on CodePen

Link to comment
Share on other sites

Hi @smallio!

 

The best questions are the newbie questions! How else would beginners benefit otherwise ;)

 

I think I get your question. To pass a callback inside a callback, you need to have a reference to the said callback to be nested.

 

Looking at your code, I struggle a bit because it seems to me you're using jQuery, not a criticism... I don't use it and get very, very, very confused with it as it has a lot of functionality that I am unaware of. So, help me out if I write something here that's wrong or you're already aware of.

 

Side comment, what are all those libraries you are loading in your pen? Do you need them all? Again, sorry if I am missing something, I'm just trying to predict behaviour based on the libraries.

 

Anyhow, back to the theory. It should be something as simple as:

 

 

Mind you, there are several other ways of doing this. They will vary depending how you want to structure your code, handle scope and whatever library you are using.

 

ps: Nice transition.

  • Like 4
Link to comment
Share on other sites

Hey @Dipscom

 

Thanks for the codepen!

 

I've pretty much figured it out with a few tweaks & your post. The only thing that's randomly changed is the counter fails to stop at 100 now it's being called back. Can you see any reason why this would happen?

 

Thanks again,

Smallio

 

 

Link to comment
Share on other sites

44 minutes ago, Dipscom said:

Why do you call it on line 72 and then again onStart of your tween? What is that function trying to achieve? One call you pass a param, the second you don't.

 

Very good question I looked over that.

 

I only want to fire it on line 82, I just can't get the params to work there.

 

I want the (25) & (100) passed on line 82 as well I'm just not sure how to delete the timing param (25) from line 68 and move it to 82.

 

I'm sure it's super simple, I'm probably messing up a bracket or something!

Link to comment
Share on other sites

6 hours ago, Dipscom said:

Looking at your code, I struggle a bit because it seems to me you're using jQuery, not a criticism... I don't use it and get very, very, very confused with it as it has a lot of functionality that I am unaware of. So, help me out if I write something here that's wrong or you're already aware of.

 

 

Also in reference to this, what should I be using instead of JQuery? If you find it confusing, no wonder I do as well aha. 

Link to comment
Share on other sites

Passing params is simple, from the docs (https://greensock.com/docs/TweenMax) (in the gray box):

 

Quote
onStartParams:  Array - An Array of parameters to pass the onStart function. For example, TweenMax.to(mc, 1, {x:100, onStart:myFunction, onStartParams:[mc, "param2"]}); To self-reference the tween instance itself in one of the parameters, use "{self}", like: onStartParams:["{self}", "param2"]

 

 

So, in your code you would do something like:

 

tl.from(countUp, 0.6, {
 opacity:0, ease:Expo.easeOut,
 onStart: countItUp,
 onStartParams: [100]
});

 

 

3 minutes ago, smallio said:

Also in reference to this, what should I be using instead of JQuery? If you find it confusing, no wonder I do as well aha. 

 

I make no recomendations. I do not criticize jQuery. It has its place and applications.

 

It is just that when I started back into web development, I was working in banner development and we cannot afford libraries that are not 100% required. GSAP is, otherwise no animation. jQuery not because as @OSUblake says: 'http://youmightnotneedjquery.com/' :D

 

So, nowadays I'm just more comfortable without it than with it.

  • Like 3
Link to comment
Share on other sites

1 hour ago, Dipscom said:

Passing params is simple, from the docs (https://greensock.com/docs/TweenMax) (in the gray box):

 

 

 

So, in your code you would do something like:

 


tl.from(countUp, 0.6, {
 opacity:0, ease:Expo.easeOut,
 onStart: countItUp,
 onStartParams: [100]
});

 

 

 

I make no recomendations. I do not criticize jQuery. It has its place and applications.

 

It is just that when I started back into web development, I was working in banner development and we cannot afford libraries that are not 100% required. GSAP is, otherwise no animation. jQuery not because as @OSUblake says: 'http://youmightnotneedjquery.com/' :D

 

So, nowadays I'm just more comfortable without it than with it.

 

Thanks for all the helpful info!!! I've bookmarked http://youmightnotneedjquery.com/ 8-)

 

I understand the params. My problem lies in passing more then one. As seen here  -

 

exhibit a) These are the params I'm trying to move to exhibit c

function countItUp(numb) {
  var secondsLabel = document.querySelector(".js-count-up");
  var totalSeconds = 0;
 
  var countdown = setInterval(function(){
    totalSeconds++;
    secondsLabel.innerHTML = totalSeconds;
  
    if (totalSeconds >= numb) {
      clearInterval(countdown);
    } 
  }, 25);
}
countItUp(100);

 

exhibit B) function without params (calling them in timeline)

function countItUp(numb) {
  var secondsLabel = document.querySelector(".js-count-up");
  var totalSeconds = 0;
 
  var countdown = setInterval(function(){
    totalSeconds++;
    secondsLabel.innerHTML = totalSeconds;
  
    if (totalSeconds >= numb) {
      clearInterval(countdown);
    } 
  })
};

 

exhibit c) now I need to add them both back here. The 100 param I understand but no matter what I do with the (25) param it gives me console errors.

tl.from(countUp, 0.6, {
     opacity:0, ease:Expo.easeOut,
     onStart: countItUp(100),
  });

 

I assume it looks something like this after reading the documentation yet this does not work :'(

tl.from(countUp, 0.6, {
     opacity:0, ease:Expo.easeOut,
     onStart: countItUp[25, 100],
  });

 

I feel like I'm going full retard here :/

  • Haha 1
Link to comment
Share on other sites

2 hours ago, smallio said:

I feel like I'm going full retard here :/

 

The feeling is mutual.

 

I really don't get the 25 and the 100... What are you counting? What is the 25? And the 100? Why do you need to pass 25 and 100 into the function?

 

If you want to pass more than one value to your function, then you will need to amend your function to accomodate it.

 

Do you want the 25 inside countItUp to be a param? You need to alter your function accordingly.

 

// If your function isn't set to receive more than one parameter then, it won't do anything with the extra params
function countItUp(numb, interval) {
  var secondsLabel = document.querySelector(".js-count-up");
  var totalSeconds = 0;
  
  // If you want to use either a given param or a default value
  var intrvl = interval || 25;
 
  var countdown = setInterval(function(){
    totalSeconds++;
    secondsLabel.innerHTML = totalSeconds;
  
    if (totalSeconds >= numb) {
      clearInterval(countdown);
    } 
  }, intrvl);
}


// Then you will be able to pass two values in your onStart
tl.from(countUp, 0.6, {
 opacity:0, ease:Expo.easeOut,
 onStart: countItUp,
 onStartParams: [100, 25]
});

 

Be careful not to be invoking the method when defining the tween

// this bad
// it will fire immediately, not when the timeline's playhead starts playing this tween
tl.from(countUp, 0.6, {
  onStart: countItUp(100)
})


// you need to pass a Params as well
tl.from(countUp, 0.6, {
  onStart: countItUp,
  onStartParams: [100]
})

 

Notice how the Params is an array, it is so because a JavaScript function can have any number of arguments and therefore, Params must be able to accept any number of items.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

5 minutes ago, Dipscom said:

 

The feeling is mutual.

 

I really don't get the 25 and the 100... What are you counting? What is the 25? And the 100? Why do you need to pass 25 and 100 into the function?

 

If you want to pass more than one value to your function, then you will need to amend your function to accomodate it.

 

Do you want the 25 inside countItUp to be a param? Then, you need to alter your function accordingly.

 


// If your function isn't set to receive more than one parameter then, it won't do anything with the extra params
function countItUp(numb, interval) {
  var secondsLabel = document.querySelector(".js-count-up");
  var totalSeconds = 0;
  
  // If you want to use either a given param or a default value
  var intrvl = interval || 25;
 
  var countdown = setInterval(function(){
    totalSeconds++;
    secondsLabel.innerHTML = totalSeconds;
  
    if (totalSeconds >= numb) {
      clearInterval(countdown);
    } 
  }, intrvl);
}


// Then you will be able to pass two values in your onStart
tl.from(countUp, 0.6, {
 opacity:0, ease:Expo.easeOut,
 onStart: countItUp,
 onStartParams: [100, 25]
});

 

Be careful not to be invoking the method when defining the tween


// this bad
// it will fire immediately, not when the timeline's playhead starts playing this tween
tl.from(countUp, 0.6, {
  onStart: countItUp(100)
})


// you need to pass a Params as well
tl.from(countUp, 0.6, {
  onStart: countItUp,
  onStartParams: [100]
})

 

Notice how the Params is an array, it is so because a JavaScript function can have any number of arguments and therefore, Params must be able to accept any number of items.

 

IT WORKED!!!! Thank you so much man!!

 

If you have a tip jar/btc address I'd love to buy you a coffee for all the help.

 

Learned so much from this thread it's unreal :) 

Link to comment
Share on other sites

Hey @Dipscom I present another cake points earning opportunity :-o

 

Due to the length of the animation I've made I decided it actually looks better just halving it reversing it.

 

Thus my count-up timer stays at 0. What could I do to solve this? I've tried flipping the > symbol as well as reversing total seconds and the numb on start param. No cigar as of yet. 

 

function countItUp(numb, interval) {
    var secondsLabel = document.querySelector(".js-count-up");
    var totalSeconds = 0;

    // If you want to use either a given param or a default value
    var intrvl = interval || 25;

    var countdown = setInterval(function() {
        totalSeconds++;
        secondsLabel.innerHTML = totalSeconds;

        if (totalSeconds >= numb) {
            clearInterval(countdown);
        }
    }, intrvl);
}

/* myTimeline | Logo/Text/Counter */
function myTimeline() {
    var tl = new TimelineMax();
    tl.to(wave, 1, { attr: { d: shape2 }, ease: Expo.easeIn });
    tl.to(wave, 1, { attr: { d: shape3 }, ease: Expo.easeOut });
    tl.to(wave, 1, { ease: Expo.easeOut, opacity: 1 });

    /*** CALL FUNCTION WITH THE TWEEN BELOW ***/
    tl.from(countUp, 0.6, {
        opacity: 0,
        ease: Expo.easeOut,
        onStart: countItUp,
        onStartParams: [100, 15]
    });

var masterOut = new TimelineMax({
    repeat: 0,
    repeatDelay: 0
});

masterOut.add(myTimeline());

console.log("duration is: " + masterOut.duration());

masterOut.reverse(0);

		});
});

 

Link to comment
Share on other sites

You know up to this day I still don't know where this countItUp is being used...

 

In any case, you're triggering a setInterval on start of  your Tween, there's nothing linking them together. The setInterval has no idea what the timeline is doing and so, cannot react to anything it does.

 

If you want to count up some numbers while the tween is playing, you're better off by having GSAP do it for you.

 

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

 

Link to comment
Share on other sites

@Dipscom ooo thank you :)

 

Okay so I've put this in a timeline now, tried everything and when I hit reverse nothing happens. Just for the record I'm not trying to reverse the countdown... I'll just reverse the params so it plays forwards. My actual animation is just to complex now to reverse manually and have this play forward as normal.

 

What would you suggest?

 

See the Pen PEMQqm by smallio (@smallio) on CodePen

 

Link to comment
Share on other sites

1 minute ago, Dipscom said:

What doesn't reverse?

 

Also if you use a .fromTo on your countup, it will always count the same set of numbers by just repeating it without the need to reset any variables.

 

See the Pen MrNBvK by dipscom (@dipscom) on CodePen

 

 

Ah ffs, I was literally about to do that! Bingo! Thank you dude :)))

 

Does not work in my actual timeline because I forgot I was getting the value from tl.progress. but you gave me an idea to call this timeline from the main timeline. Even when reversing it'll still play it normally, Wow, had no idea you could do this. I'm gonna be making everything in chain sub timelines from now on... The possibilities are endless!

 

Emma might be a lil' salty about all this cake I owe now. 

Link to comment
Share on other sites

As you're using TimelineMax, there's no need to use a function to have a back and forth repeat. I only used that because I assumed you wanted to trigger a reverse when something else happened.

 

See the Pen EoqqvR?editors=0010 by dipscom (@dipscom) on CodePen

 

Nesting timelines is the way to go. You will be able to create crazy complicated sequences without losing your mind and ending up with 5 kilos of spaghetti.

 

If you feel you can handle moar awesomeness: https://medium.com/net-magazine/7-hidden-gems-of-the-greensock-animation-platform-4fb71389f6ca

 

12 hours ago, smallio said:

Emma might be a lil' salty about all this cake I owe now. 

 

Well, if the two of you are on first-name terms, surely you can sweet talk her into understanding the value of some charity.

  • Like 2
  • Haha 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...