Jump to content
Search Community

useGSAP with Advanced Timeline Orchestration

iDVB test
Moderator Tag

Recommended Posts

In a complex react application using the passing down a timeline prop outline here, what is the best / correct way to orchestrate animations that are on the main timeline and nested in components.
You can see in the example we have some animations that are defined at the top level and some animations that are defined in a deeper component. How do I ensure that the second animation defined  at the top level occurs AFTER the nested components animation.

 

https://codesandbox.io/p/sandbox/gsap-animation-test-lnzldq?layout=%7B%22sidebar[…]ebar%22%3Atrue%2C%22sidebarPanelSize%22%3A15%7D

The scenario is easier if all animations are in the child components (none directly on the timeline) and the components are ordered top-to-bottom in JSX in the order we want the animations to sequence. But if you try to inject the child components into the main timeline expecting all other animations to occur after them ... things break down.  We're trying to avoid setting hard-coded position times for everything.

Surely there is a recommended way to handle this.

Link to comment
Share on other sites

Hi,

 

This is a bit complicated basically from a state management point, actually this is mostly a state management issue. This is your code:

// Parent component
useGSAP(
  () => {
    const timeline = gsap.timeline();
    timeline.to("#box1", { x: 100, duration: 2 });
    timeline.add("myLabel");
    timeline.to("#box2", { x: 100, rotate: 360, duration: 2 });
    setMainTl(timeline);
  },
  { scope: ref }
);

// Child component
useGSAP(() => {
  if (!mainTl) return;
  const nestedTl = gsap.timeline();
  nestedTl.to("#box3", { x: 100, duration: 1 });
  mainTl.add(nestedTl, "myLabel");
}, [mainTl]);

So in react child components are rendered first, right? But the issue here is that when the child component first renders the main timeline doesn't exists yet. Then the parent component runs and the timeline is created. At that point the nested timeline is not added yet, in fact it doesn't exists yet so the label is created and then immediately on top of that label the next tween is added . After that the state of the parent timeline is updated using setMainTl. Only after that the child component is re-render and this time the nested timeline is created and added at that label. See the problem? This is not a GSAP issue but a react communication one. You should find the way to tell your parent component the duration of the child instances so you can add that duration to tween after the label using the position parameter. Another option is to use react context or a custom hook. Another option is to handle the master timeline in a different way and add the instances and labels after the maser timeline is created on every component. Honestly I never had to deal with something like this even after using GSAP in quite a few production react apps and components, what I can tell you is that I never used an approach like this.

 

Sorry I can't be of more assistance.

Happy Tweening!

Link to comment
Share on other sites

Thanks @Rodrigo!
I agree that it absolutely is a react-specific challenge. In the same way `useGSAP` has mitigated a number of other ones, I was hoping there might be at least a recommended approach for this. GSAP has at least acknowledged the need to pass timelines or callbacks down, it only a small step from there that seems to occur in most of our production sites that are heavily animated.
https://www.klick.com
https://careers.klick.com

https://transformation.klick.com
 

we want to avoid:
- magic/manual position number shared around
- putting all timelines in the parent and lifting up refs out of all children into parent
- we can't avoid the need to have out of sequence tweens being placed into the timeline before others need to be placed. (ideally things should shift to make room)

Link to comment
Share on other sites

hello @Rodrigo I am a colleague of @iDVB and am very curious to learn a bit more of some alternative approaches to working with GSAP in react.  You said in your response "what I can tell you is that I never used an approach like this." Do you mean that you handle gsap animations in an entirely different way than what we have done? Would love to learn more about your approach! 

 

Thanks for your reply

Link to comment
Share on other sites

@iDVB, yeah this is mostly about positioning your instances in your timeline, but the pain point is when, meaning at what point during the lifecycle of the app/component that has to be done. The methods or approaches we suggest are based on the first thing you want to avoid, manually passing a magic number.

2 hours ago, iDVB said:

we can't avoid the need to have out of sequence tweens being placed into the timeline before others need to be placed. (ideally things should shift to make room)

In that case you could look into creating some state management (most likely using React context) solution that tells you when every child is created and then populate the master timeline. While this might sound simple it surely shouldn't be the simplest thing to implement, probably not extremely complex, but definitely not easy. You could look into the shiftChildren method:

https://gsap.com/docs/v3/GSAP/Timeline/shiftChildren()

 

Maybe create the master timeline and add the labels then when some child elements are created get the time of that label and shift all the children from the time of that label by the duration of that particular Tween/Timeline you're creating in the component.

 

---

 

@cbravo

2 hours ago, cbravo said:

Do you mean that you handle gsap animations in an entirely different way than what we have done?

If I need all the animations in the same parent component (something I avoid as much as possible because in a complex scenario like this, things get complicated), create all the animations using either forward refs (last resource) or using regular text selectors, which works since the child components are rendered before the parent ones, so the elements will be at the DOM at that time.

Use a callback with React context to add to a master timeline indicating the position where it should be by hand in every component. In this case never animate a DOM element that is in the parent component, use this component only as a container and something that handles all that logic, nothing more, then place your components in your JSX in the order they should be added to the master timeline so you know that the order will be the one you expect. So in this later case there is no need to indicate a position for each timeline, maybe use the position parameter if you need to create a pause for some time between animations, so in the example @iDVB created do something like this:

return (
  <div>
    <Box id="box1" className="red" />
    <Box id="box2" className="blue" />
    <Box id="box3" className="green" />
  </div>
);

 

Finally I took some time to create a minimal demo with shifChildren and that could be what you're looking for, especially for the demo you posted originally:

https://stackblitz.com/edit/vitejs-vite-aaoopl?file=src%2FApp.jsx&terminal=dev

 

Hopefully this helps.

Happy Tweening!

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