Files
doormile_react/src/animations/AnimationProvider.tsx

104 lines
2.8 KiB
TypeScript

"use client";
import React, { useEffect } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
/**
* AnimationProvider
* Initializes GSAP + ScrollTrigger globally, refreshes on route changes,
* and provides smooth defaults.
*/
export default function AnimationProvider({ children }: { children: React.ReactNode }) {
useEffect(() => {
gsap.registerPlugin(ScrollTrigger);
// Global GSAP defaults for buttery animations
gsap.defaults({
ease: "power3.out",
duration: 0.8,
});
const initDecorativeBlocks = () => {
// Clean up previous block triggers to avoid duplicates
ScrollTrigger.getAll().forEach((t) => {
if (t.vars && (t.vars as any).id === "block-deco") {
t.kill();
}
});
const decorativeBlocks = document.querySelectorAll(".block-decoration");
decorativeBlocks.forEach((block) => {
ScrollTrigger.create({
id: "block-deco",
trigger: block,
start: "top 92%",
onEnter: () => {
setTimeout(() => {
block.classList.add("animated");
}, 150);
},
onEnterBack: () => {
setTimeout(() => {
block.classList.add("animated");
}, 150);
},
onLeave: () => {
block.classList.remove("animated");
},
onLeaveBack: () => {
block.classList.remove("animated");
},
});
});
};
// Run initializations
initDecorativeBlocks();
// Refresh ScrollTrigger at staggered intervals to account for lazy-loaded assets/images over the network
const timeouts = [
setTimeout(() => {
initDecorativeBlocks();
ScrollTrigger.refresh(true);
}, 100),
setTimeout(() => {
initDecorativeBlocks();
ScrollTrigger.refresh(true);
}, 500),
setTimeout(() => {
initDecorativeBlocks();
ScrollTrigger.refresh(true);
}, 1500),
setTimeout(() => {
initDecorativeBlocks();
ScrollTrigger.refresh(true);
}, 3000),
];
// Refresh on full window load (when all images, styles, and fonts are in place)
const handleLoad = () => {
initDecorativeBlocks();
ScrollTrigger.refresh(true);
};
window.addEventListener("load", handleLoad);
// Also refresh on window resize
const handleResize = () => {
initDecorativeBlocks();
ScrollTrigger.refresh(true);
};
window.addEventListener("resize", handleResize);
return () => {
timeouts.forEach(clearTimeout);
window.removeEventListener("load", handleLoad);
window.removeEventListener("resize", handleResize);
ScrollTrigger.getAll().forEach((t) => t.kill());
};
}, []);
return <>{children}</>;
}