This commit is contained in:
2026-03-31 14:03:41 +02:00
parent 399d78e508
commit d567fa3e02
14 changed files with 336 additions and 153 deletions

View File

@@ -11,10 +11,11 @@ gsap.registerPlugin(SplitText)
const GsapContext = createContext<{
addAnimation: (
animation: gsap.core.TimelineChild,
position: gsap.Position
position: gsap.Position,
tlId?:string
) => void,
resetTimeline: () => void,
resumeTimeline: () => void,
resetTimeline: (tlId?:string) => void,
resumeTimeline: (tlId?:string) => void,
getScroller: () => Element | Window | null
} | null>(null)
@@ -22,59 +23,103 @@ export function useGsapContext() {
return useContext(GsapContext)
}
export const useTimeLine = (dep?:any,all?:boolean) => {
export const useTimeLine = (dep?:any,all?:boolean,tlId?:string,) => {
console.log(tlId)
const gsapContext = useGsapContext()
useEffect(() => {
if (dep instanceof Array && all) {
let acc = true;
let allDepsSatisfied = dep.reduce((p,c) => c !== undefined && p ,acc )
if (allDepsSatisfied) {
gsapContext?.resumeTimeline()
gsapContext?.resumeTimeline(tlId)
}
} else {
if (dep) {
gsapContext?.resumeTimeline()
gsapContext?.resumeTimeline(tlId)
}
}
},[dep])
useLayoutEffect(() => {
return () => {
gsapContext?.resetTimeline()
gsapContext?.resetTimeline(tlId)
}
},[])
}
export default function GsapProvider({ children }: { children: ReactNode }) {
export default function GsapProvider({ children,timelines }: { children: ReactNode,timelines?:string[] }) {
const timeLines = useRef<Map<string,gsap.core.Timeline>|null>(null)
const tl = useRef<gsap.core.Timeline | null>(null)
const scrollerRef = useRef<Element | Window | null>(null)
const getScroller = useCallback(() => {
const cached = scrollerRef.current
if (!cached || (cached instanceof Element && !document.contains(cached))) {
scrollerRef.current = document.querySelector('[data-slot="scroll-area-viewport"]') ?? window
}
// const cached = scrollerRef.current
// if (!cached || (cached instanceof Element && !document.contains(cached))) {
let scrollers = document.querySelectorAll('[data-slot="scroll-area-viewport"]')
if (scrollers.length < 1) {
scrollerRef.current = window
} else {
let scrollerArray = Array.from(scrollers.values()).sort((a,b) => {
const s1 = a as HTMLDivElement;
const s2 = b as HTMLDivElement;
// using bitwise not (~~) to coerce NaN values to 0
const aPriority = ~~Number(s1.dataset?.scrollerPriority)
const bPriority = ~~Number(s2.dataset?.scrollerPriority)
return aPriority - bPriority;
})
let prioScroller = scrollerArray.pop();
scrollerRef.current = prioScroller || window;
}
// }
return scrollerRef.current
}, [])
useGSAP(() => {
if (!timeLines.current && timelines) {
timeLines.current = new Map()
}
timelines?.forEach((tlId) => {
timeLines.current?.set(tlId,gsap.timeline({id:tlId,paused:true}))
})
if (!tl.current) {
tl.current = gsap.timeline({ paused: true })
}
return () => { console.log("gsap cleanup") }
})
const addAnimation = useCallback((animation: gsap.core.TimelineChild, position: gsap.Position) => {
const addAnimation = useCallback((animation: gsap.core.TimelineChild, position: gsap.Position,tlId?:string) => {
if(tlId) {
const selectedTimeLine = timeLines.current?.get(tlId)
console.log("add animation to:", position, selectedTimeLine !== undefined)
selectedTimeLine?.add(animation,position)
return;
}
console.log("add animation to:", position, tl.current !== undefined)
tl.current?.add(animation, position);
},[])
const resetTimeline = useCallback(() => {
console.log('resetting timeline')
tl.current?.kill()
tl.current?.revert()
ScrollTrigger.getAll().forEach(st => st.kill())
tl.current = gsap.timeline({paused:true})
const resetTimeline = useCallback((tlId?:string) => {
console.log("resetting timeline",tlId)
if (tlId) {
let selectedTimeLine = timeLines.current?.get(tlId)
selectedTimeLine?.kill()
selectedTimeLine?.revert()
timeLines.current?.set(tlId,gsap.timeline({id:tlId,paused:true}))
} else {
tl.current?.kill()
tl.current?.revert()
tl.current = gsap.timeline({paused:true})
}
ScrollTrigger.getAll().forEach(st => {
st.kill()
})
},[])
const resumeTimeline = useCallback(() => {
console.log("resuming timeline:",tl.current)
tl.current?.resume()
const resumeTimeline = useCallback((tlId?:string) => {
if (tlId) {
console.log("trying to resume timeline",tlId)
let selectedTimeLine = timeLines.current?.get(tlId)
selectedTimeLine?.resume()
} else {
console.log("resuming default timeline")
tl.current?.resume()
}
},[])
return (
<GsapContext.Provider value={{ addAnimation, resetTimeline, resumeTimeline, getScroller }}>