Jump to content
GreenSock

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

Adding / Removing Elements Mid Animation

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,

 

I'm working with timelines, and after certain steps, it sometimes makes sense to add / remove elements from the DOM. Something like this:
 

tl.to('.element', 1, { /*params to change*/})

tl.to('.element', .5, { /*params to change*/,

  onComplete: () => //figure out if i need to add some elements and then add them

})

tl.to('.newElements', 1, { /*params to change*/})

 

I was facing problems for a while where nodes I added ('.newElements' above) wouldn't animate. Eventually I tried adding those elements before the animation started, with an opacity of 0, and then just animating them in at the appropriate time afterwards. This fixed the issue.

 

Is this the appropriate way of doing things, or can I in-fact add elements during onComplete callbacks, mid-timeline, and then animate on those newly added elements?

 

And if I must have elements in the DOM before starting an animation / timeline that will eventually use them, what are the ramifications of this for nested timelines? I've been working on breaking up some of my animations into smaller pieces, that can then be reused and hacked together in different ways (see this post). Some of those discreet actions, inherently require DOM manipulation. So for example if I want to update a chart with new data, I may need to add some elements first. So lets say I have a updateData function that:

  • checks the DOM for what is and isn't there
  • adds new elements if there isn't already an element in the DOM for each of the data points that needs to be represented
  • updates elements that already exist but whose data has changed
  • removes elements that are no longer needed.

 

This function in the end, returns a timeline. Could I then nest this timeline inside another timeline like so..?


 

//tl is a timeline to update all charts at once

tl.add(updateChart1())

tl.add(updateChart2())

tl.add(updateChart3())

 

...Where each updateChart#  returns a timeline that also had code adding and removing elements.

Link to comment
Share on other sites

1 hour ago, dude said:

Is this the appropriate way of doing things, or can I in-fact add elements during onComplete callbacks, mid-timeline, and then animate on those newly added elements?

Timelines are generally meant to be static. It would be very expensive to have timelines check on every tick "do I have a reference for this new element yet?". So in general it's a good idea to create any elements you need before the timeline is ran. 

 

1 hour ago, dude said:

Could I then nest this timeline inside another timeline like so..?

In general, yes. But, as stated above, it would be good to do all of these adds before running the tl. 

 

There are work arounds for adding to timelines mid animation but it is not recommended.

 

If you run into particular issues or want more finite help of best practices it would be good to create a minimal demo of your situation that we can look at and interact with.

  • Like 2
Link to comment
Share on other sites

On 9/6/2019 at 9:59 AM, ZachSaucier said:

It would be very expensive to have timelines check on every tick "do I have a reference for this new element yet?". So in general it's a good idea to create any elements you need before the timeline is ran. 

What about instead of on each tick, just on each piece of the timeline (each "to", "from", "stagger", etc). Or does that come out to the same thing in terms of how it'll run?

 

On 9/6/2019 at 9:59 AM, ZachSaucier said:

So in general it's a good idea to create any elements you need before the timeline is ran. 

 

On 9/6/2019 at 8:06 AM, dude said:

Could I then nest this timeline inside another timeline like so..?

In general, yes. But, as stated above, it would be good to do all of these adds before running the tl. 

 

There are work arounds for adding to timelines mid animation but it is not recommended.

Ok, a quick clarification. And to do so I'm going to make a crappy diagram (below). The verticle line represents a master timeline (tl0), and the horizontal lines represent nested timelines (tl1, tl2, tl3, tl4), which are returned by calling their respective functions (fn1, fn2, fn3, fn4).

 

tl0

|

|_____ fn1 -> tl1

|__________ fn2 -> tl2

|________ fn3 -> tl3

|

|_______________  fn4 -> tl4

 

suppose fn2 does some dom manipulation before starting the timeline (tl2) and returning it. If this function were to be executed on its own (not as part of tl0), this should count as doing all the dom stuff before the timeline (tl2) runs, correct? What about once it's nested inside tl0 though? Technically tl2 is a different timeline object than tl0, so would this be allowed (so long as I make sure none of the other timelines need the removed dom elements)?

 

If this is still too confusing and you want me to just put together a code example, let me know.

 

And thanks for taking the time :)

 

Link to comment
Share on other sites

18 hours ago, dude said:

What about instead of on each tick, just on each piece of the timeline (each "to", "from", "stagger", etc). Or does that come out to the same thing in terms of how it'll run?

Obviously the less ticks you have to do custom logic the better, but it boils down to pretty much the same thing in terms of how it'll run.

 

In terms of your example, I suggest having a function like so:

 

function setupTimeline() {
  var tl1 = fn1(),
      tl2 = fn2(),
      tl3 = fn3(),
      tl4 = fn4,
      mainTL = new TimelineMax();
  
  mainTL.add(tl1).add(tl2).add(tl3).add(tl4);
  
  return mainTL;
}

That way you do all of the DOM manipulation beforehand, add your timelines in the way that you want, and have everything set up before playing the main timeline.

 

A code example would make it more clear...

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