Jump to content
Search Community

Issue with looping multiple timelines

neworigin test
Moderator Tag

Go to solution Solved by GreenSock,

Recommended Posts

Hello there again, 

 

In the ongoing struggle I created a new topic as I've got the gradient animation sorted (thanks again!).

 

I am now seeing an issue with trying to loop multiple timelines. The attached pen is close but I am seeing a the logo (white bars) restart after a quick second once the timeline loops.

 

This seems to happen if I put more than a half second here: 

 

.call(animLogo, null, ">-0.75")

 

The idea is to have a slight overlap of the timelines when they loop so the gap isn't so long at the end. 

See the Pen vYmaRGY by neworigin (@neworigin) on CodePen

Link to comment
Share on other sites

When a timeline gets too complicated, I just break everything down into functions and let it run that way.

 

step1();

function step1() {
  
  gsap.timeline()
    .to(".foo", { x: 100 })
    .add(step2, "-=0.25")
}

function step2() {
  
  gsap.timeline()
    .to(".bar", { x: 100 })
    .add(step3, "-=0.25")
}

function step3() {
  
  gsap.timeline()
    .to(".baz", { x: 100 })
    .add(step1, "-=0.25")
}

 

  • Like 1
Link to comment
Share on other sites

That's a totally valid technique - just beware that it's embedding function calls into the timeline instead of the actual animations themselves, so you cannot effectively control the entire animation as a whole (which may be absolutely fine, depending on your use case). For example, you couldn't pause() the sequence or reverse() or timeScale(). Here's what I often do:

function step1() {
  let tl = gsap.timeline();
  tl.to(".foo", {x: 100})
    .to(...); // add more animations...
  return tl; // RETURN THE TIMELINE!
}

function step2() {
  let tl = gsap.timeline();
  tl.to(".bar", {y: 100})
    .to(...); // add more animations...
  return tl; // RETURN THE TIMELINE!
}

function step3() {
  let tl = gsap.timeline();
  tl.to(".baz" {x: 100})
    .to(...); // add more animations...
  return tl; // RETURN THE TIMELINE!
}
    
let master = gsap.timeline();
master.add(step1())
  .add(step2(), "-=0.25"); // overlap by 0.25 seconds
  .add(step3(), "+=0.5");  // 0.5 second gap

Now we can control the entire sequence very easily with master.pause(), master.reverse(), master.timeScale(0.5) or whatever. And of course you can repeat the whole thing by adding a repeat to the master. 

 

In terms of having the appearance of the start of the sequence overlapping with the end, that can be a bit tricky but usually it's a matter of adding something to the end of the animation that mimics that overlap and gets to the starting state right before it loops. For example, if box1 starts out opacity: 1 and then you crossfade 10 boxes in a sequence and you want box10 to crossfade with box1 to start the loop over again, you'd add that crossfade to the END of the timeline so that box1 ends at opacity: 1 so that when it loops to the start, it appears seamless. 

 

Sometimes you may have an initial animation (like if the whole screen is blank and you fade box1 in just at the very start), you'd handle that part of the animation independently just to kick things off, and then once box1 is opacity1, THAT is where you start the repeating timeline. 

 

Happy tweening!

  • Like 3
Link to comment
Share on other sites

Thanks for the responses! I had initially taken an approach with functions but my main issue is I want timeline 1 to restart before timeline 2 ends as the gap at the end is too long. I guess I'm not seeing a way to do that with your approaches above.

 

Any idea why my version is getting that restart for the second timeline when it loops?

Link to comment
Share on other sites

9 minutes ago, neworigin said:

I had initially taken an approach with functions but my main issue is I want timeline 1 to restart before timeline 2 ends as the gap at the end is too long. I guess I'm not seeing a way to do that with your approaches above.

Sure, BOTH approaches mentioned above could work. Why don't you give it a shot and then if you need help, post your minimal demo and we'll take a peek. 

 

You could even do something like: 

function buildAnimation() {
  let tl = gsap.timeline();
  tl.to(...); // do your animations
  tl.add(buildAnimation, "-=0.5"); // start fresh animation 0.5 seconds before the end.
}

 

  • Like 1
Link to comment
Share on other sites

  • Solution
56 minutes ago, neworigin said:

Any idea why my version is getting that restart for the second timeline when it loops?

Here's your problem:

function resetYear() {
	tl2.pause();
	tl2.time(0); // <-- drags the playhead back to 0, triggering the callback
}

You're moving the playhead backward from the end all the way to the beginning, so it'll trigger any callbacks inbetween because you didn't set the suppressEvents parameter to true. Think of it like a record - setting suppressEvents (2nd parameter) to true is like picking up the needle and dropping it in the new position. Otherwise, it's like dragging the needle across the record. 

 

The simplest solution is to just use the time parameter of the pause() method. The suppressEvents defaults to true on that method (unlike time() and totalTime() which are more like scrubbers). 

 

tl2.pause(0);

 

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