Files
gregorlohaus.com/src/app/_components/Animated/AnimateIn.tsx
2026-03-14 18:35:04 +01:00

31 lines
1.3 KiB
TypeScript

import { useGSAP } from "@gsap/react";
import { useRef, type ReactNode } from "react";
import { useGsapContext } from "~/app/_providers/GsapProvicer";
import { SplitText } from "gsap/SplitText";
import gsap from 'gsap'
const AnimateTextIn = ({children,animation="type",position}:{children:ReactNode,animation?:"type"|"slide",position:gsap.Position}) => {
const el = useRef<HTMLDivElement>(null)
const gsapContext = useGsapContext();
useGSAP(() => {
const rect = el.current?.getBoundingClientRect()
const isInView = rect && rect.top < window.innerHeight
const chars = new SplitText(el.current,{type:'chars'})
gsapContext?.addAnimation(gsap.to(el.current,{opacity:100, duration:0}),0)
const fromVars = animation === "slide"
? {opacity:0, x:-10, duration: 0.2, stagger: {each: 0.08}, ease:'bounce.inOut'}
: {opacity:0, duration: 0.01, stagger: {each: 0.04}, ease: 'bounce.inOut'}
if (isInView) {
gsapContext?.addAnimation(gsap.from(chars.chars, fromVars),position)
} else {
gsap.from(chars.chars, { ...fromVars, scrollTrigger: { trigger: el.current, start: 'top 85%', scroller: gsapContext?.getScroller() } })
}
}, { dependencies: [] })
return (
<div ref={el} className="opacity-0">
{children}
</div>
)
}
export default AnimateTextIn;