Jump to content
Search Community

Multiple pins causing second pin to break

Akash Ranjan test
Moderator Tag

Recommended Posts

Hello,

I am stuck into a weird problem. I am working in next JS and I have two components that have the identical animations. The problem is that the pin of first element is causing the pin of second element to break as you can see on codepen. Can you please tell me what I am doing wrong here.

 

This is the code I am using inside both the components. Selectors are different for both of them.

 

Please help me

  useEffect(() => {
    if (window.innerWidth > 767) {
      let ctx = gsap.context(() => {
        let serviceSection = document.querySelector('.service-block');
        gsap.to('.service-block', {
          x: () => serviceSection.scrollWidth * -1,
          xPercent: 100,
          scrollTrigger: {
            trigger: '.service-block',
            start: '0% 20%',
            end: '+=2000px 10%',
            pin: serviceWrapper.current,
            scrub: 0.5,
            invalidateOnRefresh: true,
            // markers: true,
          },
        });
      }, serviceWrapper.current);

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

 

 

Thank You

See the Pen MWRGqwm by akashrwx (@akashrwx) on CodePen

Link to comment
Share on other sites

Hi,

 

In React always use the useGSAP hook, is far simpler and cleaner:

https://gsap.com/resources/React

 

Here is a simple demo that uses the useGSAP hook with GSAP MatchMedia:

https://stackblitz.com/edit/vitejs-vite-pfhzkf?file=src%2FApp.jsx

 

Also in your codepen you're using the same element as the trigger:

gsap.to(".work-block", {
  x: () => horizontalSection.scrollWidth * -1,
  xPercent: 100,
  scrollTrigger: {
    trigger: ".work-block", // FIRST TRIGGER
    start: "center center",
    start: "0% 50%",
    end: "+=2000px 30%",
    pin: ".work-wrapper-main",
    scrub: true,
    invalidateOnRefresh: true,
    markers: true
  }
});

gsap.to(".work-block-2", {
  x: () => horizontalSection2.scrollWidth * -1,
  xPercent: 100,
  scrollTrigger: {
    trigger: ".work-block", // FIRST TRIGGER AGAIN HERE!!!
    start: "center center",
    start: "0% 50%",
    end: "+=2000px 30%",
    pin: ".work-wrapper-main-2",
    scrub: true,
    invalidateOnRefresh: true,
    markers: true
  }
});

Changing that to trigger: ".work-block-2" seems to work the way you expect.

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

Hey @Rodrigo,

 

Thanks for your reply. I tried useGSAP hook but still I am having the same problem. It is working on my codepen but not in my project. It is a strange issue as if I dont put the elements in separate components and keep the code as it is on the page with both the useGSAP hooks it works. But if I make components for both of them the second one breaks.

The problem is the second pin scrolltrigger start point is off from the amount of pinspacing from the first element. I tried removing pin from first element and second element started working fine. I dont know what is causing this issue. Please help :(

 

  useGSAP(
    () => {
      const mm = gsap.matchMedia();
      mm.add(
        {
          small: '(max-width: 767px)',
          large: '(min-width: 768px)',
        },
        (ctx) => {
          const { small } = ctx.conditions;
          let serviceSection = document.querySelector('.service-block');
          gsap.to('.service-block', {
            x: () => serviceSection.scrollWidth * -1,
            xPercent: 100,
            scrollTrigger: {
              trigger: '.service-block',
              start: '0% 20%',
              end: '+=2000px 10%',
              pin: serviceWrapper.current,
              scrub: 0.5,
              // invalidateOnRefresh: true,
              // markers: true,
            },
          });
        }
      );
    },
    {
      scope: homeMain,
    }
  );
// component

import React, { useEffect, useRef } from 'react';
import Heading from '../Heading/Heading';
import FeaturedWork from '../FeaturedWork/FeaturedWork';
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/dist/ScrollTrigger';
import { useGSAP } from '@gsap/react';

const workContent = [
  {
    projectName: 'NextGen Marketplace',
    projectType: 'E-COMMERCE PLATFORM DEVELOPEMENT',
    projectUrl: '/',
  },
  {
    projectName: 'NextGen Marketplace',
    projectType: 'E-COMMERCE PLATFORM DEVELOPEMENT',
    projectUrl: '/',
  },
  {
    projectName: 'NextGen Marketplace',
    projectType: 'E-COMMERCE PLATFORM DEVELOPEMENT',
    projectUrl: '/',
  },
  {
    projectName: 'NextGen Marketplace',
    projectType: 'E-COMMERCE PLATFORM DEVELOPEMENT',
    projectUrl: '/',
  },
  {
    projectName: 'NextGen Marketplace',
    projectType: 'E-COMMERCE PLATFORM DEVELOPEMENT',
    projectUrl: '/',
  },
];

gsap.registerPlugin(ScrollTrigger);
const SelectedWorkSection = ({ className }) => {
  const workWrapper = useRef();
  const main = useRef();

  useGSAP(
    () => {
      const mm = gsap.matchMedia();
      mm.add(
        {
          small: '(max-width: 767px)',
          large: '(min-width: 768px)',
        },
        (ctx) => {
          const { small } = ctx.conditions;
          let workSection = document.querySelector('.work-block');

          gsap.to('.work-block', {
            x: () => workSection.scrollWidth * -1,
            xPercent: 100,
            scrollTrigger: {
              trigger: '.work-block',
              start: 'center center',
              start: '0% 20%',
              end: '+=2000px 10%',
              pin: workWrapper.current,
              scrub: 0.5,
              invalidateOnRefresh: true,
              markers: true,
            },
          });
        }
      );
    },
    {
      scope: main,
    }
  );
  return (
    <section ref={main} className={`section-pad overflow-hidden ${className}`}>
      <div className="container">
        <Heading className="mb-12 " icon>
          Selected Work
        </Heading>
      </div>
      <div className=" ">
        <div className="container">
          <div className="work-wrapper-main " ref={workWrapper}>
            <div className="work-wrapper">
              <div
                className={`flex h-full work-block flex-wrap md:flex-nowrap gap-8 md:gap-0`}
              >
                {workContent.map(
                  ({ projectName, projectType, projectUrl }, index) => (
                    <div key={index} className="md:min-w-[50%] md:px-4 ">
                      <FeaturedWork
                        initialText={`0${index + 1}`}
                        projectName={projectName}
                        projectType={projectType}
                        projectLink={projectUrl}
                      />
                    </div>
                  )
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
};

export default SelectedWorkSection;

 

Link to comment
Share on other sites

Hi,

 

Unfortunately there is not a lot we can do without a minimal demo. If you have your ScrollTrigger instances in different components, be sure to use the right selectors and scoping.

 

Try to create a minimal demo on Stackblitz that clearly replicates the issue, please don't use the full project or a git repo since that makes it more difficult to fork and find the issues since we have to go through a lot of files and lines of code, the simpler the better.

 

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