88 lines
2.7 KiB
TypeScript
88 lines
2.7 KiB
TypeScript
'use client'
|
|
import { useGSAP } from '@gsap/react'
|
|
import gsap from 'gsap'
|
|
import { SplitText } from 'gsap/SplitText'
|
|
import { ScrollTrigger, GSDevTools } from 'gsap/all'
|
|
import { createContext, useCallback, useContext, useEffect, useRef, type ReactNode } from 'react'
|
|
|
|
gsap.registerPlugin(useGSAP)
|
|
gsap.registerPlugin(ScrollTrigger)
|
|
gsap.registerPlugin(SplitText)
|
|
gsap.registerPlugin(GSDevTools)
|
|
const GsapContext = createContext<{
|
|
addAnimation: (
|
|
animation: gsap.core.TimelineChild,
|
|
position: gsap.Position
|
|
) => void,
|
|
resetTimeline: () => void,
|
|
resumeTimeline: () => void,
|
|
getScroller: () => Element | Window | null
|
|
} | null>(null)
|
|
|
|
export function useGsapContext() {
|
|
return useContext(GsapContext)
|
|
}
|
|
|
|
export const useTimeLine = (dep:any,all?:boolean) => {
|
|
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()
|
|
}
|
|
} else {
|
|
if (dep) {
|
|
gsapContext?.resumeTimeline()
|
|
}
|
|
}
|
|
},[dep])
|
|
useEffect(() => {
|
|
return () => {
|
|
gsapContext?.resetTimeline()
|
|
}
|
|
},[])
|
|
}
|
|
|
|
export default function GsapProvider({ children }: { children: ReactNode }) {
|
|
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
|
|
}
|
|
return scrollerRef.current
|
|
}, [])
|
|
useGSAP(() => {
|
|
if (!tl.current) {
|
|
tl.current = gsap.timeline({ paused: true, id:'mainTimeline', onComplete: ()=>{
|
|
console.log('timeline revert')
|
|
gsap.getById('mainTimeline')?.revert()
|
|
} })
|
|
}
|
|
return () => { console.log("gsap cleanup") }
|
|
})
|
|
|
|
const addAnimation = useCallback((animation: gsap.core.TimelineChild, position: gsap.Position) => {
|
|
console.log("add animation to:", position, tl.current !== undefined)
|
|
tl.current?.add(animation, position);
|
|
},[])
|
|
const resetTimeline = useCallback(() => {
|
|
tl.current?.kill()
|
|
tl.current?.revert()
|
|
ScrollTrigger.getAll().forEach(st => st.kill())
|
|
tl.current = gsap.timeline({paused:true})
|
|
},[])
|
|
const resumeTimeline = useCallback(() => {
|
|
console.log("resuming timeline:",tl.current)
|
|
tl.current?.resume()
|
|
},[])
|
|
return (
|
|
<GsapContext.Provider value={{ addAnimation, resetTimeline, resumeTimeline, getScroller }}>
|
|
{children}
|
|
</GsapContext.Provider>
|
|
)
|
|
}
|