Jump to content
Search Community

Animated Continuous Sections with GSAP ScrollTrigger

vanss472 test
Moderator Tag

Go to solution Solved by Rodrigo,

Recommended Posts

I'm trying to recreate the GSAP Observer demo but using ScrollTrigger instead. My issue is when you scroll, I see a black frame at the end of every slide. Any advice would be greatly appreciated. I'm also trying to use `position: absolute` for each section is that possible using ScrollTrigger? I want to be able to control the vertical scrolling, and then snap after the user is idle for like 5 seconds.

 

GSAP Observer:

See the Pen XWzRraJ by GreenSock (@GreenSock) on CodePen

 

GSAP ScrollTrigger

See the Pen MWzQoNY by Vanss472-the-decoder (@Vanss472-the-decoder) on CodePen

Edited by vanss472
Add more context.
Link to comment
Share on other sites

Hi @vanss472 and welcome to the GreenSock forums!

 

The main problem is the fact that you're trying to re-use the same logic that works fine for Observer in ScrollTrigger. The approach is a bit different actually.

 

I think this example could provide a better starting point for what you're trying to achieve:

See the Pen NWxNEwY by GreenSock (@GreenSock) on CodePen

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

Hi,

 

This is just about the end point config in your ScrollTrigger config. Something like this works a bit better: end: "+=" + ((sliderArr.length - 1) * 100) + "%". Give that a try and let us know how it works.

 

Finally I'd recommend you to watch this short video that @Cassie made that goes a bit into detail about this:

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

Hi @Rodrigo, I think I'm still approaching this the wrong way. Correct me if I'm wrong, by pinning the `container` instead of each slide it would be hard to track the scroll position, right? Because I'm also trying to add animation(bg and nav items) on each slide when it hits the center of the viewport.

Link to comment
Share on other sites

Hi,

 

In this particular example there is no such thing as each slide hitting the center of the screen because they are all stacked on top of each other and you are animating the ClipPath of each element at different moments or positions in your timeline.

 

If you want to do something when each slide animates in you have to do it in the forEach loop here:

slides.current.forEach((slide, index) => {
  slidesTl.to(slide, {
    clipPath: "polygon(0% 100%, 100% 100%, 100% 0%, 0% 0%)"
  });
});

That code adds a new instance to the timeline that is controlled by ScrollTrigger. You can add other instances there and use the position parameter so things happen in the order you intend.

 

Hopefully this helps.

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

Hi @Rodrigo, you are saying in my case is it not possible to track the center of the screen using the ScrollTrigger end markers? Would I need to play with the timeline position parameter in order to trigger any animation?

 

I updated my CodePen:

1. Any idea why the slideToSection scrollTo would not work?
2. Related to my question above, I added another ScrollTrigger instance inside the slides forEach and I was able to add the end marker to the bottom of slide 2 & 3.


See the Pen abQYeLB by Vanss472-the-decoder (@Vanss472-the-decoder) on CodePen

Link to comment
Share on other sites

  • Solution

Hi,

 

Indeed in the case of setting the active you're using an onUpdate method which is very expensive because is ran on every slide on every update. Better use a call() method with the position parameter checking the current index and the direction of the ScrollTrigger instance:

slides.current.forEach((slide, index) => {
  if (index > 0) {
    slidesTl.current
      .to(slide, {
      clipPath: "polygon(0% 100%, 100% 100%, 100% 0%, 0% 0%)"
    })
      .call(() => {
      const _d = slidesTl.current.scrollTrigger.direction;
      setActiveNavItem(index + (_d > 0 ? 0 : _d));
    }, null, "-=0.5")
  }
});

I stored the timeline in a ref in order to use it in the click event. In that case the click wasn't working because all your slides top position is the same, so obviously the top position calculated by the ScrollTo Plugin will be the same. In this cases the best approach is to use the start and end point of the ScrollTrigger instance and use the current slide index to estimate where the ScrollTo Plugin should tween the window scroll value:

const slideToSection = (index) => {
  const factor = navItems.current.length - 1;
  const st = slidesTl.current.scrollTrigger;
  gsap.to(window, {
    scrollTo: {
      y: st.start + ((st.end - st.start) * (1 / factor * index)),
    },
    duration: 1
  });
};

Here is a fork of your codepen:

See the Pen jOQpPGO by GreenSock (@GreenSock) on CodePen

 

Hopefully this helps.

Happy Tweening!

  • Thanks 1
Link to comment
Share on other sites

Hi,

 

That is just the defaults settings for a timeline instance. From the Timeline docs:
 

Defaults
Anything in the defaults object of a timeline gets inherited by its child animations when they get created, so if you find yourself setting the same ease or duration (or any value) over and over again, this can help make your code more concise.
Any defaults you set this way will get pushed into every child tween - it's not limited to a certain subset of properties. Inherited defaults are easily overwritten anytime a property is declared on a child animation.

 

Hopefully this helps.

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

Hey @Rodrigo, I'm back with another question. I want to add a parallax effect to the image/video. I currently have something happening when you start scrolling you'll see the media that is been reveal have a subtle effect but I also want to have the effect on the media that is being removed from the viewport. Any good tips? Thanks!

 

.fromTo(
    bg.current[index].firstElementChild,
      {
         y: () => slide.offsetHeight * 0.2
      },
      {
         y: 0
      },
        "<"
   )

 


See the Pen abQYeLB by Vanss472-the-decoder (@Vanss472-the-decoder) on CodePen

Link to comment
Share on other sites

Hey @Rodrigo, so it does make sense in the example above but when I try on my it doesn't quite work the same. It looks like in my case using a negative value doesn't work as expected. Any other tip? Thanks!

 

.fromTo(
  bg.current[index].firstElementChild,
   {
        y: () => (index ? slide.offsetHeight * 0.2 : 0)
   },
   {
        y: () => -slide.offsetHeight * 0.2
   },
   "<"
   )

 

Link to comment
Share on other sites

Hi,

 

Honestly I couldn't tell you without spending quite some time looking at the way your project is structured and how it works. Unfortunately we don't have the time resources to provide general consulting or custom complex solutions for our users. You should try setting the size of your images (right now you have height and width set to 100% in your CSS) based on the parallax animation you'll be creating. There is no question that they need to be bigger, the challenge is to make that happen for different screen sizes and width/height ratios and the amount of pixels you want to animate the image on the Y axis. Maybe just set percentages and use yPercent would be the first thing I'd try.

 

Hopefully this helps and good luck with your project!

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