Jump to content
Search Community

Width/Height Flashing with GSAP Flip.fit in Next.js ("One Element Scroll" Animation)

epenflow
Moderator Tag

Go to solution Solved by Rodrigo,

Recommended Posts

Posted

I'm attempting to replicate the "One Element Scroll" animation from Tympanus.net (https://tympanus.net/Development/OneElementScroll/) using GSAP Flip.fit within a NextJs. However, i'm experiencing an issue where the width and height of the element with the class .one flicker between its full size and the final size set by Flip.fit. 

Minimal reproduction :
i've created a simplified NextJs project on StackBlitz to isolate the issue:
https://stackblitz.com/edit/stackblitz-starters-dykskccl?file=app%2F_components%2Fmain.tsx

 

 
  • Solution
Posted

Hi @epenflow and welcome to the GSAP Forums!

 

Your demo is far from being minimal (over 300 lines of code) and seems to be working as expected. Please reduce the demo to the bare minimum or just the part that is not working, or the first thing that is not working so we can have a look at some isolated code and behaviour. We don't have the time resources to go through all that code trying to figure it out how everything works while trying to find possible problems and issues, is beyond the help we provide in these free forums. Maybe a simple codepen demo of the part that is not working might be enough, regardless of the framework is just JS, HTML and CSS, so that should be enough as well.

Posted

Hi thank you for your response.  I apologize if the length caused any incovenience.
I'm encounter an issue with Flip.fit where the element with the class .one flickers during the animation. It seems to render twice, first at its full width and height, then abruptly transition to the final size of the Flip states
 

 function createFlipOnScrollAnimation(
      oneElementElement | null,
      parentElementElement | null
    ) {
      const stepElementsHTMLElement[] = gsap.utils.toArray('[data-step]');

 

      if (flipContext.currentflipContext.current.revert();

 

      flipContext.current = gsap.context(() => {
        const states = stepElements.map((step=> Flip.getState(step));

 

        const timeline = gsap.timeline({
          scrollTrigger: {
            trigger: parentElement,
            start: 'clamp(center center)',
            endTrigger: stepElements[stepElements.length - 1],
            end: 'clamp(center center)',
            scrub: true,
            immediateRender: false,
            // markers: true,
          },
        });

 

        states.forEach((stateindex=> {
          timeline.add(
            Flip.fit(oneElementstate, {
              duration: 1,
              ease: index === 0 ? 'none' : 'sine.inOut',
            }) as GSAPAnimation,
            index ? '+=0.5' : 0
          );
        });
      });
    }

 

 
Posted

Yeah that doesn't really help I'm afraid, since there is nothing wrong GSAP-wise in that code you posted.

 

The only thing I can think about it is that there could be a flaw in the way you're implementing the useGSAP hook here:

useGSAP(
  () => {
    if (!containerRef.current)
      throw new Error(
        `Missing Container Reference : Please ensure containerRef is properly injected.`
      );
    const oneElement = containerRef.current.querySelector('.one');
    const parentElement = oneElement!.parentElement;

    createFlipOnScrollAnimation(oneElement, parentElement);
    animateSpansOnScroll();
    animateImageOnScroll();
    addParallaxToText();
    animateFilterOnFirstSwitch(oneElement);
    addParallaxToColumnImages();

    window.addEventListener('resize', () => {
      createFlipOnScrollAnimation(oneElement, parentElement);
    });
  },
  { scope: containerRef, dependencies: [] }
);

Then your methods look like this:

function createFlipOnScrollAnimation(
oneElement: Element | null,
 parentElement: Element | null
) {
  const stepElements: HTMLElement[] = gsap.utils.toArray('[data-step]');

  if (flipContext.current) flipContext.current.revert();

  flipContext.current = gsap.context(() => {
    const states = stepElements.map((step) => Flip.getState(step));

    const timeline = gsap.timeline({
      scrollTrigger: {
        trigger: parentElement,
        start: 'clamp(center center)',
        endTrigger: stepElements[stepElements.length - 1],
        end: 'clamp(center center)',
        scrub: true,
        immediateRender: false,
        // markers: true,
      },
    });

    states.forEach((state, index) => {
      timeline.add(
        Flip.fit(oneElement, state, {
          duration: 1,
          ease: index === 0 ? 'none' : 'sine.inOut',
          // scale: true,
          // absolute: true,
        }) as GSAPAnimation,
        index ? '+=0.5' : 0
      );
    });
  });
}

There are a few things that caught my attention. You're using GSAP Context inside your method, there is no need for that since useGSAP uses GSAP Context internally. Second is about the fact that you're just creating the GSAP instances inside your methods. That doesn't work since useGSAP is not aware of those instances since they are created in a different execution context so the hook can't revert them properly. For that your methods either have to return every instance they create (more convoluted and verbose) or they should be wrapped around the contextSafe method the useGSAP hook returns:

https://gsap.com/resources/React#making-your-animation-context-safe

 

Finally by default the useGSAP hook uses an empty dependencies array, so there is no need to pass that.

 

Give that a try and if you keep having issues, please reduce the demo to just that initial Flip instance being created inside the useGSAP.

 

Happy Tweening!

Posted

Hi,

 

I'm not really sure what the problem is in the codepen you posted (the stackblitz demo seems to be working as expected) but this is how it looks without any GSAP code in it:

See the Pen wBwqWrB by GreenSock (@GreenSock) on CodePen.

 

As you can see the width of the box is never 400px, so there is something in the CSS that could be causing this 🤷‍♂️

 

As for what you're trying to achieve maybe this simpler demo can get you on the right direction:

See the Pen VYZzjMV by GreenSock (@GreenSock) on CodePen.

 

Hopefully this helps

Happy Tweening!

Posted

I recreate your given example to next js but still i've encountered the same issue. I don't know why this is happens, but i think i'll use gsap set to set the initial height and width.

  • 4 weeks later...

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