portfolio/src/hooks/useScrollReveal.ts

65 lines
1.2 KiB
TypeScript
Raw Normal View History

2026-04-22 15:40:44 +02:00
import { useLayoutEffect, useRef } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
interface ScrollRevealOptions {
y?: number;
x?: number;
duration?: number;
delay?: number;
stagger?: number;
start?: string;
ease?: string;
}
export function useScrollReveal<T extends HTMLElement>(
options: ScrollRevealOptions = {}
) {
const ref = useRef<T>(null);
useLayoutEffect(() => {
const el = ref.current;
if (!el) return;
const {
y = 40,
x = 0,
duration = 0.8,
delay = 0,
stagger = 0.1,
start = "top 85%",
ease = "power3.out",
} = options;
const children = el.children.length > 0 ? el.children : [el];
gsap.set(children, { opacity: 0, y, x });
const tween = gsap.to(children, {
opacity: 1,
y: 0,
x: 0,
duration,
delay,
stagger,
ease,
scrollTrigger: {
trigger: el,
start,
toggleActions: "play none none none",
},
});
return () => {
tween.kill();
ScrollTrigger.getAll().forEach((st) => {
if (st.trigger === el) st.kill();
});
};
}, []);
return ref;
}