Jump to content
GreenSock

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

Pause nested timeline created from function call

Recommended Posts

We all know using functions to generate timelines is the way to go but sometimes I find myself needing to stop halfway inside the child timeline but without creating a master timeline scrubber.

 

But for the life of me, I can't pause the nested animation. I can fake it by adding a .call() in the child to pause the master but I assumed if I paused the child, the master timeline would stop as well. But it does not seem the case. Is that expected behaviour?

 

See the attached pen for a super-duper simple example.

 

Ta.

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

  • Like 1

Share this post


Link to post
Share on other sites

Children don't tell their parents what to do... at least well behaved children don't.

 

Think about elements. A child element cannot change the position of its parent, and it cannot stop its parent's position from changing.

 

So you would need to do to do something like this. Not pretty, but when you see repetition, that usually means you can use a loop to simplify things.

 

var master = new TimelineLite()
  .add(fadeIn(".d1"))
  .addPause()
  .add(fadeOut(".d1"))
  .add(fadeIn(".d2"))
  .addPause()
  .add(fadeOut(".d2"))
  .add(fadeIn(".d3"))
  .addPause()
  .add(fadeOut(".d3"))

function fadeIn(el) {
  return new TimelineLite().from(el, 0.5, {xPercent:-50, autoAlpha:0})
}

function fadeOut(el) {
  return new TimelineLite().to(el, 0.5, {xPercent:50, autoAlpha:0}, "+=0.2")
}

 

 

  • Like 3
  • Haha 2

Share this post


Link to post
Share on other sites

Thanks for the demo with your question.

Blake beat me to the punch with those pesky children trying to control their parents.

 

Like Blake said, the paused state of a child animation does not affect the paused state of its parent. Pausing the parent will always pause the children. The position of the parent’s playhead dictates what is rendered in all child animations. This is a very purposeful design rule that dictates how the entire engine performs. 

 

Stepping back a bit, consider that GSAP has a root timeline that all animations belong to. When you create even a simple TweenLite tween it is added to this root timeline

 

var t = TweenLite.to("body", 1, {rotation:1})
console.log(t.timeline); // logs out a timeline

 

 

It is very good that pausing t does not pause the root timeline thus making every animation pause. Of course Jack could write code that made it so that the root timeline doesn’t get paused in this case, but its good to have consistent behavior throughout. I can understand in your situation how you would like pausing the child to pause the parent, but I think in the grand scheme of things the current design makes the most sense in the most common use-cases.

 

Imagine if pausing the parent did not make the children stop playing? you would have to identify every child tween and pause it (I know you’re not suggesting that).

 

That probably doesn’t give the most clear or accurate explanation of why pausing the child doesn’t pause the parent, but hopefully you trust me that it works that way for good reason and maybe Jack can find the obvious thing I’m not remembering;)


As for your demo, its an interesting scenario. The timeline that is created inside your function has no idea what timeline it is being put inside of after it gets created and returned so there is no great way to write code in there that says “pause my parent”. Your current solution of using call() to call a function that pauses the parent is probably the best thing there is but it isn’t entirely accurate as some minuscule amount of time will elapse while the function is being called and code is being executed. So the pause will not happen at the exact same time your call() happens. A few milliseconds of time drift probably won’t impact what you’re doing but figured I’d mention it anyway. This is the very reason we created a specific addPause() function so that it would ensure the timeline gets paused exactly when it should. Prior to addPause() folks were writing there own calls() to pause the timeline.

 

For pausing the parent with call(), the only slight enhancement I can offer is dynamically finding the parent of the timeline that the call() is in like:

console.clear();
function fadeInOut(el) {
    var tl = new TimelineLite({id:"child"});
    tl.from(el, 0.5, {xPercent:-50, autoAlpha:0})
    tl.call(pauseMyParent);
    tl.to(el, 0.5, {xPercent:50, autoAlpha:0}, '+=0.2');
    return tl;
}

var master = new TimelineLite({id:"master"})
master.add(fadeInOut('.d1'))
master.add(fadeInOut('.d2'))
master.add(fadeInOut('.d3'))
function pauseMyParent() {
  console.log(this.timeline.vars.id);
  console.log(this.timeline.timeline.vars.id)
  this.timeline.timeline.pause();
}
$("#resume").click(function(){
  master.resume();
})


See the Pen vJjwWp?editors=1111 by hansel234 (@hansel234) on CodePen


Maybe that helps a little. Don’t know. There will still be some slight time-drift. 

  • Like 4

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×