|
// <DIR>/src/hooks/useLocoScroll.js |
|
|
|
import gsap from "gsap"; |
|
import ScrollTrigger from "gsap/ScrollTrigger"; |
|
import { useEffect } from "react"; |
|
import LocomotiveScroll from "locomotive-scroll"; |
|
|
|
// REPLACE THIS WITH YOUR STYLES |
|
import "@styles/locomotive-scroll.scss"; |
|
|
|
gsap.registerPlugin(ScrollTrigger); |
|
|
|
// |
|
// PUT YOUR CONFIG HERE |
|
// -------------------------------- |
|
|
|
const mobileBreakpoint = 1024; |
|
const scrollOptions = { |
|
// https://github.com/locomotivemtl/locomotive-scroll#instance-options |
|
container: "#___gatsby", |
|
options: { |
|
smooth: true, |
|
smoothMobile: false, |
|
getDirection: true, |
|
touchMultiplier: 2.5, |
|
lerp: 0.15, |
|
class: "is-reveal", |
|
}, |
|
}; |
|
|
|
//----------------------------- |
|
|
|
let locoScroll = null; |
|
|
|
// Updating LS on scrolltrigger refresh |
|
const lsUpdate = () => { |
|
if (locoScroll) { |
|
locoScroll.update(); |
|
} |
|
}; |
|
|
|
const initScrolltrigger = (scrollEl) => { |
|
if (locoScroll) { |
|
locoScroll.on("scroll", ScrollTrigger.update); |
|
ScrollTrigger.removeEventListener("refresh", lsUpdate); |
|
|
|
ScrollTrigger.scrollerProxy(scrollEl, { |
|
scrollTop(value) { |
|
if (locoScroll) { |
|
return arguments.length |
|
? locoScroll.scrollTo(value, 0, 0) |
|
: locoScroll.scroll.instance.scroll.y; |
|
} |
|
return null; |
|
}, |
|
scrollLeft(value) { |
|
if (locoScroll) { |
|
return arguments.length |
|
? locoScroll.scrollTo(value, 0, 0) |
|
: locoScroll.scroll.instance.scroll.x; |
|
} |
|
return null; |
|
}, |
|
getBoundingClientRect() { |
|
return { |
|
top: 0, |
|
left: 0, |
|
width: window.innerWidth, |
|
height: window.innerHeight, |
|
}; |
|
}, |
|
// LocomotiveScroll handles things completely differently on mobile devices - it doesn't even transform the container at all! So to get the correct behavior and avoid jitters, we should pin things with position: fixed on mobile. We sense it by checking to see if there's a scroll class on the html-tag. |
|
pinType: document |
|
.querySelector("html") |
|
.classList.contains("has-scroll-smooth") |
|
? "transform" |
|
: "fixed", |
|
}); |
|
|
|
ScrollTrigger.addEventListener("refresh", lsUpdate); |
|
ScrollTrigger.refresh(); |
|
} |
|
}; |
|
|
|
// LOCO SCROLL HOOK |
|
export default function useLocoScroll() { |
|
useEffect(() => { |
|
const scrollEl = document.querySelector(scrollOptions.container); |
|
|
|
locoScroll = new LocomotiveScroll({ |
|
el: scrollEl, |
|
...scrollOptions.options, |
|
}); |
|
|
|
// RESPONSIVE DESTROY / INIT |
|
window.scroll = locoScroll; |
|
window.addEventListener("resize", () => { |
|
// resetting scroll on mobile |
|
if (window.innerWidth < mobileBreakpoint) { |
|
if (locoScroll) { |
|
locoScroll.stop(); |
|
locoScroll.destroy(); |
|
window.scroll = null; |
|
} |
|
locoScroll = false; |
|
|
|
// fetching elements with data-scroll attributes |
|
let els = [ |
|
...document.querySelectorAll("[data-scroll-section]"), |
|
...document.querySelectorAll("[data-scroll]"), |
|
]; |
|
|
|
// resetting inline transform stlyes |
|
els.forEach((el) => { |
|
el.style.transform = ""; |
|
}); |
|
} else { |
|
// start a new instance and wire up scrolltrigger to it fresh |
|
if (!locoScroll) { |
|
console.log("starting new instance"); |
|
locoScroll = new LocomotiveScroll({ |
|
el: scrollEl, |
|
...scrollOptions.options, |
|
}); |
|
locoScroll.update(); |
|
initScrolltrigger(scrollEl); |
|
} |
|
} |
|
}); |
|
|
|
initScrolltrigger(scrollEl); |
|
|
|
return () => { |
|
if (locoScroll) { |
|
ScrollTrigger.removeEventListener("refresh", lsUpdate); |
|
window.scroll = null; |
|
locoScroll.destroy(); |
|
locoScroll = null; |
|
console.log("Kill", locoScroll); |
|
} |
|
}; |
|
}); |
|
} |
|
|