Jump to content
GreenSock

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

Finish a timeline before another starts from click

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

If you look at the Codepen demo you will see I have three buttons, each linked to a different timeline. Clicking a button starts a timeline, which then pauses. 

 

I have two issues: 

 

1)  I don't want a button click to start a timeline if one is already active. I tried changing the test to  

    if ( ( timelines[1].progress() === 0 ) && ( !timelines[current].isActive() ) ) {

but that doesn't work. 

 

2) My button code would obviously be better in a for loop, but if I do that JSLint says I shouldn't declare functions within a loop. I've googled for solutions but what I've found has been hacky or inelegant. Any ideas how I can solve that?

 

I've been using GreenSock for about a week, and I love it! Great design.

 

See the Pen mykjb by jamesjohnson (@jamesjohnson) on CodePen

Link to comment
Share on other sites

(I've just noticed the title of my post doesn't match the content. That is because the title is another issue I'm having with the same code, but one which I think I've solved, or at least have some ideas I can try out.)

Link to comment
Share on other sites

Thanks for creating the demo. It was very helpful.

 

The following code satisfies the goal of each button plays its own timeline only when other timelines aren't playing

//loop through each butt (never thought I'd say that)
$(".butt").each(function(index, element){
  //assign each butt a timeline 
  element.timeline = timelines[index];
  //each butt will do the same things when clicked
  $(element).click(function(){
    //first if current isn't defined, this means this is the first butt clicked and we can tell its timleine to play with no further checks
    if (!current){
      current = this.timeline;
      current.play();
    //now we know there is a current timeline, if it is NOT active then we can set a new current and tell it to play
    } else if (current.isActive() === false){
      current = this.timeline;
      current.play();
    }
  })
})

 

http://codepen.io/GreenSock/pen/CeBDr?editors=001

 

The basic premise is that 

  • each button is assigned a timline
  • the value current tracks the most recently played timeline
  • each time a button is clicked we check to see IF there is a current timeline
    • if no current timeline then play the button's timeline and assign it to current
    • if there is a current timeline, check to see if it isActive()
      • if current timeline is not active then assign the button's timeline to current and tell it to play
      • if current timeline is active do nothing
  • Like 2
Link to comment
Share on other sites

Thank you! Wonderful support. 

 

I've almost managed to get my code working completely as I wanted. Here it my latest version:

 

See the Pen BbuLh by jamesjohnson (@jamesjohnson) on CodePen

 

The only thing I haven't been able to work out - how do I only play the current animation once the previous has finished? 

 

i.e. here:

previous = current;
current = this.timeline;
      
previous.play();
current.play(); // I want this to play after the previous one has finsihed.
Link to comment
Share on other sites

Sorry, I'm getting a little tangled up in the logic.

 

Can you please describe the exact use case you are trying to solve like

 

user presses button 1

number 1 starts moving right

user presses button 2 before number 1 finishes

 

-- what needs to be done here? --

 

-- what happens if the user doesn't press any buttons? should the next timeline play? how will there be a previous is there isn't a new current?

 

-- what happens if timeline 1 is past the first pause point and is playing back to the left and someone hits button 1 again? does timeline 1 become previous and current?

 

those questions are just rhetorical to illustrate that there seems to be a lot that needs to be explained depending on which button is pushed and which part of the animation is in progress.

Link to comment
Share on other sites

Hi Carl and jamesbcn  :)

 

i hastily changed a bit the james codepen , maybe this helps to make better logic  :roll:

 

See the Pen qLKCf by anon (@anon) on CodePen

Link to comment
Share on other sites

Carl,

 

What I want is this. 

 

1) The user presses a button, (say "Animate one"), that animation plays until the pause point (1 moves to the right).

2) The user presses another button, (say "Animate two"). This causes two things to happen:

    a. The previous animation plays the second half (1 moves back to the left).

    b. Once this has completed, the selected animation plays (2 moves to the right). 

 

(I made this codepen to try to solve the mechanics of a more complex animation I am creating, where each button gives an animation about a different subject, and the second half of each timeline is just making a neat transition between the different animations.)

Link to comment
Share on other sites

Thanks for the clarification, it certainly helps and I appreciate the nature of your reduced demo.

 

I think that since you want one animation segment to finish before another begins you now have to find a way to run functions that will check if a new animation has been requested each time an animation gets to a beginning, middle or end state. So you need animation one to trigger animation two. 

 

You could achieve this by adding callbacks to your timeline, like onComplete:checkNextAnimation, however that could involve a lot of work. 

 

What I would recommend is to use TimelineMax.tweenTo() which allows you to drive the playhead to a specific time or label and optionally fire a callback.

 

See this demo:

http://codepen.io/GreenSock/pen/aiGJB?editors=001

 

This will allow you to do things like 

 

current.tweenTo("endLabel", {onComplete:checkNextAnimation});

 

checkNextAnimation() would then be a function that sees if there is a new value for previous or current or whatever.

 

or if you want an animation to finish its animate-in portion and then check to see if a new animation has been requested do

 

current.tweenTo("recent", {onComplete:checkNextAnimation});

 

It can open a lot of possibilities without requiring you to add callbacks or pauses to your timelines. Just something to consider.

I think the majority of your challenge is in straight logic... determining what to do with each animation at various stages of interaction. 

 

Hopefully these suggestions help get you closer.

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