Jump to content
Search Community

Page transition: element is visible before animation

Lozen test
Moderator Tag

Recommended Posts

Hi there,

I'm re discovering GSAP after 6 years, I'm trying to make an animation on a little website project, it's working great except that my page can be seen before the animation, I can't figure out why 😕
Any idea or help about it please ? :)
Working with reactjs and vite js

Here is my code:

import { useRef, useEffect } from "react"
import { Link } from "react-router-dom"


import Champions from "../components/Champions"
import { gsap, Power3, Power4 } from "gsap"


import "../css/_frame.css"
import "../css/_cards.css"


const Home = props => {
    let screen = useRef(null);
    let body = useRef(null);


    useEffect(() => {
        var tl = new gsap.timeline();


        tl.to(screen, {
            duration: 1.2,
            width: "100%",
            left: "0%",
            ease: Power3.easeInOut,
        });
        tl.to(screen, {
            duration: 1,
            left: "100%",
            ease: Power3.easeInOut,
        });
        tl.set(screen, { left: "-100%" });
        gsap.to(body, {duration: 0.3}, {
            css: {
                opacity: "1",
                pointerEvents: "auto",
                ease: Power4.easeInOut
            }
        }).delay(0);
        return () => {
            gsap.to(body, {duration: 1}, {
                css: {
                    opacity: "0",
                    pointerEvents: 'none'
                }
            });
        }
    });


    return (
        <>
            <div className="load-container">
                <div className="load-screen" ref={(el) => (screen = el)}></div>
            </div>


            <div data-barba="container" className="home">
                <div ref={(el) => (body = el)} className="Headd">
                    {Object.entries(props.originData).map((origin, key) => {
                        return (
                            <div className="champions" key={key}>
                                {Object.values(origin).map((champions) => {
                                    return Object.values(champions).map((champion, key) => {
                                        return (
                                            champion.name && (
                                                <Link to={"/" + origin[0] + "/" + champion.name} key={key}>
                                                    <Champions champion={champion} />
                                                </Link>
                                            )
                                        )
                                    })
                                })}
                            </div>
                        )
                    })}
                </div>
            </div>
        </>
    )
}


export default Home

What I get in the video.

Many thanks to anyone who have read me :)
 

Link to comment
Share on other sites

Hi,

 

When using GSAP in a React app is better to use GSAP Context as shown in the resources in this page:

 

We have some starter templates here:

https://stackblitz.com/@GreenSockLearning/collections/gsap-react-starters

 

You might want to have a look at this one:

https://stackblitz.com/edit/react-6rzfpp

 

Hopefully this helps. If you keep having issues please fork one of those examples to create a minimal demo that illustrates the problems you're having.

Happy Tweening!

Link to comment
Share on other sites

20 hours ago, Rodrigo said:

Hopefully this helps. If you keep having issues please fork one of those examples to create a minimal demo that illustrates the problems you're having.

Happy Tweening!

Hi Rodrigo,

I couldn't find an answer for my issue, I did a demo in sandbox just here: sandbox demo
I couldn't import the images but we can see that we're seeing my homepage before the animation is running :(

Link to comment
Share on other sites

I don't have much time to dig into this, but I did quickly notice quite a few problems with this: 

useEffect(() => {
    var tl = new gsap.timeline();
    tl.to(screen, {
      duration: 1.2,
      height: "100%",
      ease: Power3.easeInOut,
    });
    tl.to(screen, {
      duration: 1,
      top: "100%",
      ease: Power3.easeInOut,
    });
    tl.set(screen, { left: "-100%" });
    gsap
      .to(
        body,
        { duration: 0.3 },
        {
          css: {
            opacity: "1",
            pointerEvents: "auto",
            ease: Power4.easeInOut,
          },
        }
      )
      .delay(2);
    return () => {
      gsap.to(
        body,
        { duration: 1 },
        {
          css: {
            opacity: "0",
            pointerEvents: "none",
          },
        }
      );
    };
  });
  1. You forgot to pass an empty dependency Array to the useEffect(). Without that, it'll get called on every render. 
  2. You didn't follow @Rodrigo's advice to make sure you use gsap.context() and do proper cleanup. 
  3. You're using useEffect() instead of useLayoutEffect()
  4. You're animating a Ref instead of the actual element itself, so it should be body.current instead of just body as the target
  5. You should not use "new" in front of gsap.timeline().
    // bad
    let tl = new gsap.timeline();
    
    // good
    let tl = gsap.timeline();

     

  6. You've got the wrong number of parameters in several of your tweens. For example, it should be gsap.to(target, vars) but you've got gsap.to(target, vars, vars). Maybe you meant to do a .fromTo()?
  7. You don't need a css:{} wrapper around CSS-related things. That's from about 2012. :)
  8. I'm a bit confused about why you're trying to animate something like pointerEvents
  9. You're using the very old ease syntax.
    // old
    ease: Power3.easeInOut
    
    // new
    ease: "power3.inOut"

     

So maybe you intended it to look more like this?: 

useLayoutEffect(() => {
    let ctx = gsap.context(() => {
      let tl = gsap.timeline();
      tl.to(screen.current, {
        duration: 1.2,
        height: "100%",
        ease: "power3.inOut",
      });
      tl.to(screen.current, {
        duration: 1,
        top: "100%",
        ease: "power3.inOut",
      });
      tl.set(screen, { left: "-100%" });
      gsap.to(body.current, {
          duration: 0.3,
          opacity: "1",
          pointerEvents: "auto",
          ease: "power4.inOut",
      })
        .delay(2);
    });
    
    return () => ctx.revert();
  }, []);

As for the initial transition, though, I think that has a lot more to do with logic issues in however you're doing the page/state transitions.

Link to comment
Share on other sites

Hi Jack,

Thank tou for your answer. I've just notice that I've made the old code on sandbox, sorry for this :(
Here is the actual one I'm working on, it's better but not perfect since I see a lot of differences with what you did
 

  let screen = useRef(null);
  let body = useRef(null);

  useLayoutEffect(() => {
    var tl = gsap.timeline();

    tl.to(screen, {
      duration: 1.2,
      width: "100%",
      left: "0%",
      ease: "power3.inOut",
    });

    tl.to(screen, {
      duration: 1,
      left: "100%",
      ease: "power3.inOut",
    });

    tl.set(screen, {
      left: "-100%",
    });

    gsap
      .to(body, {
        duration: 0.3,
        opacity: "1",
        pointerEvents: "auto",
        ease: "power4.inOut",
      })
      .delay(0);

    return () => {
      gsap.to(body, {
        duration: 1,
        opacity: "0",
        pointerEvents: "none",
      });
    };
  }, []);

For gsap.context I didn't get what it was doing since "revert" means 3 different things in my language, I'll ask a friend who has a better english than mine.
For the pointerEvents it's an old test I did, I though maybe I could get the event and make the page visible only after the animation in complete.

I'm gonna try to fix all of this, many thanks :)

Link to comment
Share on other sites

Yeah, there are still a lot of mistakes in the code you posted there. Why are you creating a new tween in your cleanup function in your useLayoutEffect()? You definitely shouldn't be doing that. It should only be a ctx.revert() call to revert any of the changes that GSAP made. You might want to read the docs. I'd strongly recommend reading this article: 

 

Good luck 👍

Link to comment
Share on other sites

Hi,

 

On top of Jack's advice I noticed that you're mentioning page transitions, that you're using React Router but you're not using React Transition Group which is what will allow you to create the transition hooks and timely mount/unmount the routes before and after the animations start or complete.

 

I recommend you to take a look at the Stackblitz example I posted above and see how that works in order to get a better grasp of the whole process.

 

Finally, if you're just starting with React I'd recommend you to get more traction with it before jumping to more advanced stuff as page transitions which is not and extremely complicated topic, but it shouldn't be the first project to tackle with React and GSAP.

 

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

Hi,

Thanks for the advices!
This is not my first react project, I used to do a lot of app and website on it but yes it's my first react project since more than 3 years : I did a lot of php since 3 years and it's a lot more complicated to come back to react than I though.
I didn't used gsap since... 2018 so yes I feel like I'm new to gsap 😕

  • Like 1
Link to comment
Share on other sites

If you're just getting back to GSAP, React and those kind of UI libraries, may I suggest check Vue and/or Svelte? IMHO they make your life far simpler than React in many ways. I've worked in several projects that used React over the past 6~7 years, but I always prefer to use Vue if possible and the more I look into Svelte the more I like it.

 

We also have some starter templates so you can check how to use them with GSAP:

https://stackblitz.com/@GreenSockLearning/collections/gsap-vue3-starters

 

https://stackblitz.com/@GreenSockLearning/collections/gsap-svelte-starters

 

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

Thing is I'm trying to get back to React since it's a lot more easy to find a job ^^"
I've worked on Vue only a year when it was all new, I guess vue has changed a lot ; too bad for me cause vue has a great doc (and in my language) when React has a lot of contribution but all in english ^^"

Link to comment
Share on other sites

5 hours ago, Lozen said:

Thing is I'm trying to get back to React since it's a lot more easy to find a job ^^"

Yeah, I know about that... 🙄

 

Still if you can take a peek at Vue, is true that some things have changed but is as great as it was three years ago.

 

Happy Tweening!

  • Like 1
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...