66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
import gsap from "gsap";
|
|
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
|
|
|
// Register ScrollTrigger globally once
|
|
gsap.registerPlugin(ScrollTrigger);
|
|
|
|
/**
|
|
* Custom hook to manage GSAP animations, ensuring proper cleanup.
|
|
* @param animationFn A function that defines the GSAP animation(s).
|
|
* @param dependencies Dependencies for the useEffect hook.
|
|
*/
|
|
export function useGsapAnimation(animationFn: () => gsap.core.Tween | gsap.core.Timeline | void, dependencies: React.DependencyList = []) {
|
|
useEffect(() => {
|
|
const animation = animationFn();
|
|
return () => {
|
|
// Kill the animation on unmount to prevent memory leaks
|
|
if (animation && 'kill' in animation) {
|
|
animation.kill();
|
|
}
|
|
// Also clean up ScrollTrigger instances associated with elements, if applicable.
|
|
// This is more complex and usually handled within specific component ScrollTrigger setups.
|
|
// For general cases, ensure ScrollTrigger contexts are used if many triggers are made.
|
|
};
|
|
}, dependencies);
|
|
}
|
|
|
|
/**
|
|
* Helper function for creating a simple fade-in-up animation on scroll.
|
|
*/
|
|
export const fadeInUp = (target: gsap.DOMTarget, options?: ScrollTrigger.Vars) => {
|
|
return gsap.fromTo(target,
|
|
{ autoAlpha: 0, y: 50 },
|
|
{
|
|
autoAlpha: 1,
|
|
y: 0,
|
|
duration: 1,
|
|
ease: "power3.out", scrollTrigger: {
|
|
trigger: target,
|
|
start: "top 80%", end: "bottom 20%", toggleActions: "play none none reverse", ...options
|
|
}
|
|
}
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Helper function for horizontal scroll animation.
|
|
*/
|
|
export const horizontalScroll = (section: gsap.DOMTarget, panels: gsap.DOMTarget[], options?: ScrollTrigger.Vars) => {
|
|
if (!section || !panels || panels.length === 0) return;
|
|
|
|
gsap.to(panels, {
|
|
xPercent: -100 * (panels.length - 1),
|
|
ease: "none", scrollTrigger: {
|
|
trigger: section,
|
|
pin: true,
|
|
scrub: 1,
|
|
snap: 1 / (panels.length - 1),
|
|
end: () => "+=" + section.offsetWidth, // Scrolls for the full width of the section
|
|
...options
|
|
}
|
|
});
|
|
};
|