Files
Montech_Landing/apps/landing/composables/useHeroScrollParallax.ts
T

47 lines
1.4 KiB
TypeScript
Raw Normal View History

import type { Ref } from "vue";
/**
* Scroll-scrubbed hero device parallax. GSAP is imported only on the client after mount,
* keeping it off the critical rendering path; the context is reverted on unmount.
*/
export function useHeroScrollParallax(sectionEl: Ref<HTMLElement | null>) {
let revert: (() => void) | null = null;
let disposed = false;
onMounted(async () => {
const [{ gsap }, { ScrollTrigger }] = await Promise.all([import("gsap"), import("gsap/ScrollTrigger")]);
const root = sectionEl.value;
if (disposed || !root) return;
gsap.registerPlugin(ScrollTrigger);
const laptop = root.querySelector<HTMLElement>("#hero-laptop");
const mobile = root.querySelector<HTMLElement>("#hero-mobile");
if (!laptop || !mobile) return;
const ctx = gsap.context(() => {
gsap.to(laptop, {
scrollTrigger: { trigger: root, start: "top top", end: "bottom top", scrub: 1.2 },
y: -40,
rotateY: -25,
rotateX: 13,
scale: 0.98,
ease: "none",
});
gsap.to(mobile, {
scrollTrigger: { trigger: root, start: "top top", end: "bottom top", scrub: 1.5 },
y: -85,
rotateY: -6,
rotateX: 4,
scale: 1.03,
ease: "none",
});
}, root);
revert = () => ctx.revert();
});
onBeforeUnmount(() => {
disposed = true;
revert?.();
});
}