Jump to content
Search Community

Animating dynamic path based on screen width using gsap ( React )

Rhitam
Moderator Tag

Go to solution Solved by Rodrigo,

Recommended Posts

Rhitam
Posted
Background

While following a video of JsMastery, I was introduced to the website of Zentry. I was not willing to go with the clipPath of polygon but trying to animate the dynamic paths that morphs the path of div with scroll trigger as implemented in the website. I am aware of that i haven't used the plugin of morphsvg as when is was using clipPath polygon it was working.

Problem STMT

I found that they were dynamically adjusting the clip path based on the screen width. I took 2 steps in which the shape of the div container changes. For the hero section ( section with the video playback ) the initial path as somewhat of the equation.

Step 1 -

M ${w} -3 L ${w} -3 Q ${w + 8} -3 ${w + 8} 5 L ${w + 8} 854.422 Q ${w + 8} 862.422 ${w} 862.422 L 5 862.422 Q -3 862.422 -3 854.422 L -3 5 Q -3 -3 5 -3 Z

Step 2 -

M ${0.931 * w - 34.3} 185.647 L ${0.931 * w - 34.3} 185.647 Q ${0.947 * w - 32.8} 186.339 ${0.95 * w - 28.9} 194.137 L ${0.99 * w + 2.2} 786.123 Q ${0.993 * w + 4.0} 793.92 ${0.986 * w + 2.0} 794.063 L ${-0.996 * w + 462.0} 819.577 Q ${-1.0 * w + 460.0} 819.72 ${-0.994 * w + 450.6} 812.027 L ${1.286 * w - 432.0} 98.3966 Q ${1.291 * w - 435.0} 90.7035 ${1.297 * w - 438.5} 91.3961 Z

There might be other path equations but currently i am overloaded with 2.

Solutions I Tried

Try 1 -

I tried to add a custom hook named useResponsivePath which has a useEffect hook which contains resize eventListener attached to window and when called return 2 paths based on that specific width { initial, final }

const clipPathD = useResponsivePath()
useGSAP(() => {
gsap.set("#video-frame", {
  clipPath: `path('${clipPathD.initial}')`,
});
gsap
  .timeline({
    scrollTrigger: {
      trigger: "#video-frame",
      start: "center center",
      end: "bottom center",
      scrub: true,
    },
    defaults: { ease: "power1.inOut" },
  })
  .to("#video-frame", {
    clipPath: `path('${clipPathD.initial}')`,
  });
});

Try 2 -

Since the previous approach did nothing i tried to integrate the path to an svg element

useGSAP(() => {
gsap.set("#clipPathShape", { attr: { d: paths.initial } });

gsap.timeline({
scrollTrigger: {
  trigger: "#video-frame",
  start: "center center",
  end: "bottom center",
  scrub: true,
},
defaults: { ease: "power1.inOut" },
})
.to("#clipPathShape", { attr: { d: paths.middle } });
});

And for the svg

<svg width="0" height="0">
    <clipPath id="dynamicClip" clipPathUnits="objectBoundingBox">
      <path id="clipPathShape" d="[original path i.e. the step 1]" />
    </clipPath>
  </svg>
<div
    id="video-frame"
    style={{ clipPath: "url(#dynamicClip)", WebkitClipPath: "url(#dynamicClip)" }}
  >
{ Rest of code }
</div>

Any Help is much Appreciated. Thank You

GSAP Helper
Posted

Without a minimal demo, it's very difficult to troubleshoot; the issue could be caused by CSS, markup, a third party library, a 3rd party script, etc. Would you please provide a very simple CodePen or Stackblitz that illustrates the issue? 

 

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

 

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

that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

 

Using a framework/library like React, Vue, Next, etc.? 

CodePen isn't always ideal for these tools, so here are some Stackblitz starter templates that you can fork and import the gsap-trial NPM package for using any of the bonus plugins: 

 

Please share the StackBlitz link directly to the file in question (where you've put the GSAP code) so we don't need to hunt through all the files. 

 

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

  • Solution
Rodrigo
Posted

Hi,

 

What exactly is now working in that demo? It seems to work as expected.

 

What I could suggest is to use the MorphSVG Plugin instead, is more precise and effective, given the fact that you're trying to achieve and the mask shape you're trying to implement.

https://gsap.com/docs/v3/Plugins/MorphSVGPlugin

 

 

You can check this thread by @mvaneijgen:

 

Also you can use the dependencies array and perhaps the revertOnUpdate config option in order to update the Tween when the path is updated dynamically. For that in React you can pass the path as a prop from a parent component or use a state management solution (such as React Context, Redux, Zustand, etc.):

https://gsap.com/resources/React#config-object

 

Hopefully this helps

Happy Tweening!

Rhitam
Posted

Thank you for helping me solve the issue. I wanted to generate the clipPath on #video-frame present in the component/Hero.jsx dynamically based on the width of screen, this would be used in a div. Previous function that generated the path from the custom hook 

useResponsiveClipPathHero()

in the HOC folder was also having some issue.

The issue was that i was missing the dependency array for the useGSAP function.

useGSAP(() => {
    gsap
      .timeline({
        scrollTrigger: {
          trigger: "#video-frame",
          start: "center center",
          end: "bottom center",
          scrub: true,
        },
        defaults: { ease: "power1.inOut" },
      })
      .to("#video-frame", {
        clipPath: `path('${w.middle}')`,
      });
  }, [w]);

It turns out i didnt require morphSVG plugin.

 

Thank You very much for your help.
 

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