Jump to content
Search Community

LoadIn / ScrollTrigger timeline animation

Max Hart test
Moderator Tag

Recommended Posts

Hoping someone can point me in the right direction. What i'm trying to achieve here is:

 

  • Fade in animation from [y:200,  opacity:0] to [y:0, opacity: 1] - ideally when the page loads / when the section first comes into the viewport
  • When the user scrolls down another 100vh - the elements are transitioned from [y:0, opacity: 1] to [y:200, opacity: 0] and vice versa based on the scroll direction

 

Am i going wrong somewhere currently?

 

In the grander scheme of things this approach will be used for an 'apple-esque' page that fades new content in / out based on the users scroll position - hopefully this logic will be easy to apply on a larger scale once i understand the concept of how to achieve this

 

Any help appreciated!

See the Pen QWVKWvj by maxhart (@maxhart) on CodePen

Link to comment
Share on other sites

I've forked your pen and tweaked somethings and set scrub: true to the ScrollTrigger instance. I've add some comments to your pen with explanations why I had done certain things.

 

Is this what you're looking for or do you want when the ScrollTrigger is entered animate the elements in and when the ScrollTrigger leaves animate them out. What I would do is create a ScrollTrigger instance and a separate timeline on which you create the in and out animation with a label at the beginning, middle and end of that timeline. 

 

Then within ScrollTrigger onEnter, onEnterBack, onLeave and onLeaveBack animate to the specific label you want for that call back. I hope with this feedback you are able to create what you're looking for, happy tweening!

 

See the Pen gOdwbYp?editors=0010 by mvaneijgen (@mvaneijgen) on CodePen

Link to comment
Share on other sites

Thanks for that @mvaneijgen  - i believe i've incorrectly explained my problem, let me try to clarify and please let me know if it makes sense.

 

Imagine this was a hero element at the top of a page (100vh); i want the content within it to have an 'on load' (e.g. fadeup) when the user lands on the page - unless the user has started to scroll down the page, and the hero is on its way out of the viewport - if that user journey has begun, it should load the timeline position of the contents exit animation (e.g. fadeleft) based on the scroll distance of that journey.

 

Animation B should be scrolltrigger controlled and should only start playing when the user begins scrolling to the next 100vh section of the page.

 

Would be good to know how you'd approach something like that and if i'm going down the total wrong route?

Link to comment
Share on other sites

I think i've solved this by doing the following:

  • Separate timeline for .loadin animation / elements
  • Separate timeline for .loadout animation / elements
  • loadin animation on timeline using .from
  • .loadout animation on seperate timeline using .to

 

const tl_scroll = useRef(gsap.timeline({ defaults: { opacity: 0, duration: 1 } }));
const tl_loadin = useRef(gsap.timeline({ defaults: { opacity: 0, duration: 1 } }));

const q = gsap.utils.selector(ref);

useEffect(() => {
  const ctx = gsap.context(() => {
      
      gsap.set([q('.loadin'), q('.loadout')], { autoAlpha: 1 });
      
      tl_loadin.current.from(q('.loadin'), {
        opacity: 0,
        y: 200,
        stagger: 0.125,
        duration: 1.5,
        ease: 'elastic.out(1, 0.5)',
      });

      tl_scroll.current = gsap
        .timeline({
          scrollTrigger: {
            trigger: ref.current,
            animation: tl_scroll.current,
            start: 'top top',
            end: 'bottom bottom',
            immediateRender: false,
            markers: true,
            scrub: true,
            onToggle: (self) => {
              if (self.isActive) {
                console.log('Im active!');
              }
            },
          },
        })
        .to('.loadout', { opacity: 0, y: -200, stagger: 0.125 });
      
    }, ref);
return () => ctx.revert();

 

Annoyingly, the HTML elements being used for each timeline need to be different, incase the user starts scrolling through the tl_scroll timeline before the tl_loadin timeline has finished animating (it'll try animating opacity from 1 to 0, but opacity will still be changing from 0 to 1 from the tl_loadin animation) - a small price to pay for the desired outcome!

 

Here's how that would look:

 

<div className="loadout">
  <h1 className="loadin">{formattedTitle}</h1>
</div>
<div className="loadin">
  <div className="loadout">
    {content}
  </div>
</div>
<div className="loadin">
  <a className="loadout" href={buttonUrl}>
    {buttonText}
  </a>
</div>

 

  • Like 1
Link to comment
Share on other sites

Hi @Max Forge,

 

Is great to hear that you were able to resolve your issue.

 

The one thing that I suggest you to change in your setup is this:

 

const q = gsap.utils.selector(ref);

useEffect(() => {
  const ctx = gsap.context(() => {

    gsap.set([q('.loadin'), q('.loadout')], { autoAlpha: 1 });

    tl_loadin.current.from(q('.loadin'), {
      //...
    });

    tl_scroll.current = gsap
      .timeline({
      //...
    })
      .to('.loadout', { opacity: 0, y: -200, stagger: 0.125 });

  }, ref);
  return () => ctx.revert();
}, []);

No need to create a GSAP selector instance outside the GSAP Context that already has the same ref passed as scope. This should work exactly as your current code does:

useEffect(() => {
  const ctx = gsap.context(() => {

    gsap.set(['.loadin', '.loadout'], { autoAlpha: 1 });

    tl_loadin.current.from('.loadin', {
      //...
    });

    tl_scroll.current = gsap
      .timeline({
      //...
    })
      .to('.loadout', { opacity: 0, y: -200, stagger: 0.125 });

  }, ref);
  return () => ctx.revert();
}, []);

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