parfum_agsd/parfum-shop/src/hooks/useLenisSmoothScroll.js

80 lines
1.8 KiB
JavaScript

import { useEffect, useRef } from "react";
import Lenis from "lenis";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
let scrollTriggerRegistered = false;
const registerScrollTrigger = () => {
if (!scrollTriggerRegistered) {
gsap.registerPlugin(ScrollTrigger);
scrollTriggerRegistered = true;
}
};
function useLenisSmoothScroll(dependencyKey = "") {
const lenisRef = useRef(null);
useEffect(() => {
if (typeof window === "undefined") {
return undefined;
}
const prefersReducedMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)"
).matches;
if (prefersReducedMotion) {
return undefined;
}
registerScrollTrigger();
const lenis = new Lenis({
anchors: {
duration: 1.05,
easing: (time) => 1 - Math.pow(1 - time, 4),
},
duration: 1.1,
easing: (time) => Math.min(1, 1.001 - Math.pow(2, -10 * time)),
lerp: 0.09,
smoothWheel: true,
syncTouch: false,
wheelMultiplier: 0.9,
});
lenisRef.current = lenis;
const updateScrollTrigger = () => ScrollTrigger.update();
const raf = (time) => {
lenis.raf(time * 1000);
};
lenis.on("scroll", updateScrollTrigger);
gsap.ticker.add(raf);
gsap.ticker.lagSmoothing(0);
return () => {
lenis.off("scroll", updateScrollTrigger);
gsap.ticker.remove(raf);
lenis.destroy();
lenisRef.current = null;
};
}, []);
useEffect(() => {
if (typeof window === "undefined") {
return undefined;
}
const frame = window.requestAnimationFrame(() => {
lenisRef.current?.scrollTo(0, { immediate: true, force: true });
window.scrollTo(0, 0);
ScrollTrigger.refresh();
});
return () => window.cancelAnimationFrame(frame);
}, [dependencyKey]);
}
export default useLenisSmoothScroll;