antoinelin / react-locomotive-scroll

A locomotive-scroll React wrapper
MIT License
162 stars 19 forks source link

Example of using this to bind locomotive as a proxy for GSAP ScrollTrigger #13

Open samuelgoddard opened 3 years ago

samuelgoddard commented 3 years ago

Long shot but does anyone have an example of how I would add Locomotive as a proxy for GSAP scrolltrigger with this package (as seen here with vanilla JS) -> https://codepen.io/GreenSock/pen/zYrELYe

antoinelin commented 3 years ago

As you get the scroll instance when you use useLocomotiveScroll you should be able to do whatever you like. I found this : https://greensock.com/forums/topic/24859-locomotive-scroll-direction-with-scrolltrigger/ it may possibly help you !

willslater commented 3 years ago

Has anybody actually managed to get this working with Next JS? I can get the smooth scrolling working, I can get GSAP Scroll Trigger working. But not together. I have tried with a custom hook and also with HoC but no luck as yet.

Suggestion above gives some guidance but its not exactly clear how they actually fully implemented it.

antoinelin commented 3 years ago

Erf, as I said here I think this library needs too much DIY to find how to properly use it with React. As I did not tried yet to use GSAP myself with it I can not give valuable advises, but if someone can help 🙏🏻

willslater commented 3 years ago

I managed to get it working, and mostly working well. For anyone coming in the future, i used https://www.npmjs.com/package/react-locomotive-scroll so that it gives provider and then you can get the event using hooks. One thing I needed though was a scroller proxy.

https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.scrollerProxy()

Example here with component worked. I found this on GSAP forums so cannot link to it, but the code i found is below.

import { useRef, useEffect } from "react";
import {
  LocomotiveScrollProvider,
  useLocomotiveScroll,
} from "react-locomotive-scroll";
import { gsap } from "gsap/dist/gsap";
import ScrollTrigger from "gsap/dist/ScrollTrigger";

import { Header, Footer } from "components";

gsap.registerPlugin(ScrollTrigger);

const ScrollTriggerProxy = () => {
  const { scroll } = useLocomotiveScroll();

  useEffect(() => {
    if (scroll) {
      const element = scroll?.el;

      scroll.on("scroll", ScrollTrigger.update);
      ScrollTrigger.scrollerProxy(element, {
        scrollTop(value) {
          return arguments.length
            ? scroll.scrollTo(value, 0, 0)
            : scroll.scroll.instance.scroll.y;
        },
        getBoundingClientRect() {
          return {
            top: 0,
            left: 0,
            width: window.innerWidth,
            height: window.innerHeight,
          };
        },
        pinType: element.style.transform ? "transform" : "fixed",
      });
    }

    return () => {
      ScrollTrigger.addEventListener("refresh", () => scroll?.update());
      ScrollTrigger.refresh();
    };
  }, [scroll]);

  return null;
};

const MainLayout = ({ children }) => {
    const containerRef = useRef(null);
  return (
    <>
      <LocomotiveScrollProvider
        options={{
          smooth: true,
          multiplier: 1,
          class: "is-reveal",
        }}
        watch={
          [
            //..all the dependencies you want to watch to update the scroll.
            //  Basicaly, you would want to watch page/location changes
            //  For exemple, on Next.js you would want to watch properties like `router.asPath` (you may want to add more criterias if the instance should be update on locations with query parameters)
          ]
        }
        containerRef={containerRef}
      >
        <ScrollTriggerProxy />
        <Header />
        <main data-scroll-container ref={containerRef}>
          {children}
          <Footer />
        </main>
      </LocomotiveScrollProvider>
    </>
  );
};

export default MainLayout;

Note, I could not use data-sections with it as it just ignored.

malinda666 commented 2 years ago

instead of this line, scroll.on("scroll", ScrollTrigger.update); I've used this,

scroll.on('scroll', () => {
        ScrollTrigger.update()
        ScrollTrigger.refresh()
      })

it worked perfectly in my case. even with data-scroll-section s

opr-inzn commented 1 year ago

@willslater How does this work with ScrollTrigger pin function? My content always disappears :(