I've implemented a horizontal scrolling feature using GSAP. However, when I click on a link in the nav, it does not link me to the exact location of each section.
Here's the website I've made: https://southfield-center.webflow.io/
Here's the GSAP code I used:
<script src="https://unpkg.co/gsap@3/dist/gsap.min.js"></script>
<script src="https://unpkg.com/gsap@3/dist/ScrollTrigger.min.js"></script>
<script src="https://unpkg.com/gsap@3/dist/ScrollToPlugin.min.js"></script>
<script>
gsap.registerPlugin(ScrollTrigger);
function getScrollLookup(targets, { start, pinnedContainer, containerAnimation }) {
let triggers = gsap.utils.toArray(targets).map((el) =>
ScrollTrigger.create({
trigger: el,
start: start || "top top",
pinnedContainer: pinnedContainer,
refreshPriority: -10,
containerAnimation: containerAnimation,
})
);
return (target) => {
let t = gsap.utils.toArray(target)[0];
let i = triggers.length;
while (i-- && triggers[i].trigger !== t) {}
if (i < 0) {
return console.warn("target not found", target);
}
return containerAnimation
? st.start + (triggers[i].start / containerAnimation.duration()) * (st.end - st.start)
: triggers[i].start;
};
}
// Function to initialize the scroll animation
function initScrollAnimation() {
let sections = gsap.utils.toArray(".section"),
navLinks = document.querySelectorAll(".gsap-code"),
nav = document.querySelectorAll(".nav"),
getMaxWidth = () => {
let width = 0;
sections.forEach((section) => {
const rect = section.getBoundingClientRect();
width += rect.width;
console.log(`Section ${section.id} width: ${rect.width}`);
});
return width;
},
maxWidth = getMaxWidth(),
scrollSpeed = 16,
snapProgress,
lastScrollTween = Date.now(),
curIndex = 0,
tl = gsap.timeline();
tl.to(sections, {
x: () => window.innerWidth - maxWidth,
duration: 1,
ease: "none",
});
ScrollTrigger.create({
animation: tl,
trigger: ".scrollable-div",
pin: true,
scrub: 1,
invalidateOnRefresh: true,
});
function init() {
gsap.set(sections, { x: 0 });
maxWidth = getMaxWidth();
let position = 0,
distance = maxWidth - window.innerWidth;
tl.add("label0", 0);
sections.forEach((section, i) => {
let progress = position;
const rect = section.getBoundingClientRect();
position += rect.width / distance;
tl.add("label" + (i + 1), position);
if (i < navLinks.length) {
navLinks[i].onclick = () => {
snapProgress = progress;
lastScrollTween = Date.now();
curIndex = i;
gsap.to(window, { scrollTo: maxWidth / scrollSpeed * progress, duration: 1, overwrite: "auto" });
};
}
});
}
init();
ScrollTrigger.addEventListener("refreshInit", init);
ScrollTrigger.create({
trigger: ".section_about",
start: "top top",
onToggle: (self) => {
if (self.isActive) {
gsap.set(nav, { display: "flex" });
} else {
gsap.set(nav, { display: "none" });
}
},
});
let getPosition = getScrollLookup(".section", {
start: "center center",
containerAnimation: tl,
});
navLinks.forEach((link) => {
link.onclick = (e) => {
e.preventDefault();
let target = e.target.getAttribute("href");
gsap.to(window, { scrollTo: getPosition(target), duration: 1, overwrite: "auto" });
};
});
}
if (window.innerWidth >= 992) {
initScrollAnimation();
}
</script>