Jump to content
Search Community

Gsap Toggle Class issue

Adesh test
Moderator Tag

Go to solution Solved by GreenSock,

Recommended Posts

const pinLinks = gsap.utils.toArray('.pinScroll > div');
    pinLinks.forEach((pinLink, index) => {      
        const lastpinLinks = document.querySelector('.pinScroll > div:last-child');
        ScrollTrigger.create({
            trigger: pinLink,
            start: 'top center',
            end: () => `+=${pinLink.clientHeight}`,
            toggleActions: 'play reverse none reverse',
            toggleClass: { targets: pinLink, className: "active"},
        });
    });

 

The above code works fine for me to toggleClass based on scroll, but it removes the active class from the last child, which I don't want.

Can you please tell me how can is keep active class on last child?

Link to comment
Share on other sites

It's pretty tough to troubleshoot without a minimal demo - the issue could be caused by CSS, markup, a third party library, your browser, an external script that's totally unrelated to GSAP, etc. Would you please provide a very simple CodePen or CodeSandbox that demonstrates the issue? 

 

Please don't include your whole project. Just some colored <div> elements and the GSAP code is best (avoid frameworks if possible). See if you can recreate the issue with as few dependancies as possible. If not, incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, then at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

Here's a starter CodePen that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

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

 

If you're using something like React/Next/Vue/Nuxt or some other framework, you may find StackBlitz easier to use. We have a series of collections with different templates for you to get started on these different frameworks: React/Next/Vue/Nuxt.

 

Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. 

Link to comment
Share on other sites

You mean you want it to ALWAYS be active? Then just put the active class on it and exclude it from your loop that's creating the ScrollTriggers, like this: 

See the Pen poZPVqG?editors=1010 by GreenSock (@GreenSock) on CodePen

 

I commented out your Scrollbar custom code there because none of it was working and it was just breaking the ScrollTrigger functionality. 

 

I hope that helps.

  • Like 1
Link to comment
Share on other sites

No, not at all!

If the user scrolls from the top to the section, it will be active based on position, but once we reach the last box, it will stay active. If the user scrolls back from the bottom to the top, the active class will work again based on position and keep the first box active when the user is at the top of the page.

Link to comment
Share on other sites

Hi,

 

The difference is that now you have multiple wrappers with a right section and boxes inside that one. All you have to do is loop through each of those wrappers, get the boxes for each wrapper and run the same loop Jack created in his answer.

 

Here is a fork of your last codepen:

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

 

Hopefully this clears things up. Let us know if you have more questions.

 

Happy Tweening!

Link to comment
Share on other sites

Hi,

 

You have to nest the loops. Take a good look at your code and the code from my example:

wrappers.forEach((wrapper) => {
  const q = gsap.utils.selector(wrapper);
  const pinobject = wrapper.querySelector(".left");
  const pinScroll = wrapper.querySelector(".right");
  ScrollTrigger.create({
    trigger: wrapper,
    pin: pinobject,
    pinType: "transform",
    start: "top top",
    end: () => `+=${pinScroll.clientHeight - pinobject.clientHeight}`,
    pinSpacing: false,
    scrub: true
  });

  const pinLinks = q(".right .box");
  pinLinks.forEach((pinLink, index) => {
    let isLast = pinLinks === index.length - 1,
      isFirst = pinLinks === 0;
    ScrollTrigger.create({
      trigger: pinLink,
      start: "top center",
      end: () => `+=${pinLink.clientHeight}`,
      onToggle: (self) => {
        if (self.isActive) {
          pinLink.classList.add("active");
        } else if (
          !(isFirst || isLast) ||
          (isFirst && self.progress > 0) ||
          (isLast && self.progress < 1)
        ) {
          pinLink.classList.remove("active");
        }
      }
    });
  });
});

I'm creating a loop for all the wrappers. For each wrapper I get the right side boxes and loop through those. This is not a GSAP related issue but a JS/logic handle one. I recommend you to take a pause and think about how the code I posted above works and see how the elements are selected. As you can see in the codepen example is working as expected.

 

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