49 lines
1.2 KiB
TypeScript
49 lines
1.2 KiB
TypeScript
import { useEffect, useRef } from 'react';
|
|
import gsap from 'gsap';
|
|
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
|
import type { CardAnimationConfig } from '../types';
|
|
|
|
gsap.registerPlugin(ScrollTrigger);
|
|
|
|
export function useCardAnimation(
|
|
cardsRef: React.RefObject<HTMLDivElement[]>,
|
|
config: CardAnimationConfig
|
|
) {
|
|
const animationsRef = useRef<gsap.core.Animation[]>([]);
|
|
|
|
useEffect(() => {
|
|
if (!cardsRef.current || cardsRef.current.length === 0) return;
|
|
|
|
animationsRef.current.forEach(anim => anim.kill());
|
|
animationsRef.current = [];
|
|
|
|
cardsRef.current.forEach((card, index) => {
|
|
if (!card) return;
|
|
|
|
const animation = gsap.fromTo(
|
|
card,
|
|
{ opacity: 0, y: 20 },
|
|
{
|
|
opacity: 1,
|
|
y: 0,
|
|
duration: config.duration || 0.6,
|
|
delay: (config.stagger || 0.1) * index,
|
|
scrollTrigger: {
|
|
trigger: card,
|
|
start: 'top 80%',
|
|
end: 'top 20%',
|
|
scrub: config.scrub || false,
|
|
markers: false,
|
|
},
|
|
}
|
|
);
|
|
|
|
animationsRef.current.push(animation);
|
|
});
|
|
|
|
return () => {
|
|
animationsRef.current.forEach(anim => anim.kill());
|
|
};
|
|
}, [cardsRef, config]);
|
|
}
|