Jump to content
Search Community

Extra whitespace from pin-spacer

xyzmoonlight test
Moderator Tag

Recommended Posts

 

I've been experimenting with GSAP for the past few weeks using next, and I've been trying to use "pin" with "scrollTrigger." However, it seems like I'm getting extra white space every time I use "pin" with the scroll trigger. Is there something wrong with my code? 

first, I create two refs.

const animatedPath = useRef(null)
const svgref = useRef(null)

 

and second I use `useLayoutEffect` for register scroll trigger plugin and define gasp animation

useLayoutEffect(() => {
  gsap.registerPlugin(ScrollTrigger)

  const tl = gsap.timeline({
    scrollTrigger: {
      trigger: svgref.current,
      start: "top top",
      end: "bottom 100",
      scrub: true,
      markers: true,
      pin: true
    }
  })

  gsap.set(animatedPath.current, {
    strokeDasharray: 471.2,
    strokeDashoffset: 471.2,
  })

  tl.to(animatedPath.current, {
    strokeDashoffset: 0
  })
}, [])

after that, i create svg with circle inside it

<section style={{ height: "200vh" }}>
  <svg ref={svgref} style={{ width: "400px", height: "400px" }} xmlns="http://www.w3.org/2000/svg">
    <circle cx={200} cy={200} r={75} fill="none" stroke="black" strokeWidth={10} ref={animatedPath} />
  </svg>
</section>

The result shows that the `pin-spacer` class has a large padding/whitespace, and the animation doesn't start properly.

full link https://codesandbox.io/p/sandbox/sad-lalande-q7c578?file=%2Fapp%2Fglobals.css%3A1%2C1

Thanks in advance!

Link to comment
Share on other sites

Hi there! I see you're using React -

Proper animation cleanup is very important with frameworks, but especially with React. React 18 runs in strict mode locally by default which causes your useEffect() and useLayoutEffect() to get called TWICE.

In GSAP 3.11, we introduced a new gsap.context() feature that helps make animation cleanup a breeze. All you need to do is wrap your code in a context call. All GSAP animations and ScrollTriggers created within the function get collected up in that context so that you can easily revert() ALL of them at once.

Here's the structure:

// typically it's best to useLayoutEffect() instead of useEffect() to have React render the initial state properly from the very start.
useLayoutEffect(() => {
  let ctx = gsap.context(() => {
    // all your GSAP animation code here
  });
  return () => ctx.revert(); // <- cleanup!
}, []);

This pattern follows React's best practices, and one of the React team members chimed in here if you'd like more background.

We strongly recommend reading the React information we've put together at https://greensock.com/react

Happy tweening!

Link to comment
Share on other sites

Hi,

 

Indeed using GSAP Context seems to fix the problem:

 

useLayoutEffect(() => {
  gsap.registerPlugin(ScrollTrigger)
  const ctx = gsap.context(() => {
    const tl = gsap.timeline({
      scrollTrigger: {
        trigger: svgref.current,
        start: "top top",
        end: "bottom 100",
        scrub: true,
        markers: true,
        pin: true
      }
    })

    gsap.set(animatedPath.current, {
      strokeDasharray: 471.2,
      strokeDashoffset: 471.2,
    })

    tl.to(animatedPath.current, {
      strokeDashoffset: 0
    })
  });
  return () => ctx.revert();
}, [])

Hopefully this helps.

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