55 lines
1.3 KiB
TypeScript
55 lines
1.3 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useRef } from 'react';
|
|
import gsap from 'gsap';
|
|
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
|
|
|
gsap.registerPlugin(ScrollTrigger);
|
|
|
|
interface UseCardAnimationReturn {
|
|
isMobile: boolean;
|
|
itemRefs: React.RefObject<HTMLDivElement>[];
|
|
}
|
|
|
|
export const useCardAnimation = (itemCount: number): UseCardAnimationReturn => {
|
|
const itemRefs = useRef<React.RefObject<HTMLDivElement>[]>([]);
|
|
const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;
|
|
|
|
useEffect(() => {
|
|
itemRefs.current = itemRefs.current.slice(0, itemCount);
|
|
for (let i = itemRefs.current.length; i < itemCount; i++) {
|
|
itemRefs.current[i] = { current: null };
|
|
}
|
|
}, [itemCount]);
|
|
|
|
useEffect(() => {
|
|
if (!isMobile) {
|
|
itemRefs.current.forEach((ref, index) => {
|
|
if (ref.current) {
|
|
gsap.fromTo(
|
|
ref.current,
|
|
{ opacity: 0, y: 20 },
|
|
{
|
|
opacity: 1,
|
|
y: 0,
|
|
duration: 0.6,
|
|
delay: index * 0.1,
|
|
scrollTrigger: {
|
|
trigger: ref.current,
|
|
start: 'top 80%',
|
|
end: 'top 20%',
|
|
scrub: false,
|
|
},
|
|
}
|
|
);
|
|
}
|
|
});
|
|
}
|
|
}, [isMobile]);
|
|
|
|
return {
|
|
isMobile,
|
|
itemRefs: itemRefs.current,
|
|
};
|
|
};
|