Add src/lib/animations/gsap-utils.ts

This commit is contained in:
2026-06-09 23:37:50 +00:00
parent 59d0c88a8d
commit 6fc5a31513

View File

@@ -0,0 +1,65 @@
"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
}
});
};