diff --git a/src/content/Animations/AnimatedContent/AnimatedContent.jsx b/src/content/Animations/AnimatedContent/AnimatedContent.jsx index 244af1db..2a33b7a3 100644 --- a/src/content/Animations/AnimatedContent/AnimatedContent.jsx +++ b/src/content/Animations/AnimatedContent/AnimatedContent.jsx @@ -6,6 +6,7 @@ gsap.registerPlugin(ScrollTrigger); const AnimatedContent = ({ children, + container, distance = 100, direction = 'vertical', reverse = false, @@ -16,7 +17,13 @@ const AnimatedContent = ({ scale = 1, threshold = 0.1, delay = 0, - onComplete + disappearAfter = 0, + disappearDuration = 0.5, + disappearEase = 'power3.in', + onComplete, + onDisappearanceComplete, + className = '', + ...props }) => { const ref = useRef(null); @@ -24,6 +31,12 @@ const AnimatedContent = ({ const el = ref.current; if (!el) return; + let scrollerTarget = container || document.getElementById('snap-main-container') || null; + + if (typeof scrollerTarget === 'string') { + scrollerTarget = document.querySelector(scrollerTarget); + } + const axis = direction === 'horizontal' ? 'x' : 'y'; const offset = reverse ? -distance : distance; const startPct = (1 - threshold) * 100; @@ -31,44 +44,67 @@ const AnimatedContent = ({ gsap.set(el, { [axis]: offset, scale, - opacity: animateOpacity ? initialOpacity : 1 + opacity: animateOpacity ? initialOpacity : 1, + visibility: 'visible' + }); + + const tl = gsap.timeline({ + paused: true, + delay, + onComplete: () => { + if (onComplete) onComplete(); + if (disappearAfter > 0) { + gsap.to(el, { + [axis]: reverse ? distance : -distance, + scale: 0.8, + opacity: animateOpacity ? initialOpacity : 0, + delay: disappearAfter, + duration: disappearDuration, + ease: disappearEase, + onComplete: () => onDisappearanceComplete?.() + }); + } + } }); - gsap.to(el, { + tl.to(el, { [axis]: 0, scale: 1, opacity: 1, duration, - ease, - delay, - onComplete, - scrollTrigger: { - trigger: el, - start: `top ${startPct}%`, - toggleActions: 'play none none none', - once: true - } + ease + }); + + const st = ScrollTrigger.create({ + trigger: el, + scroller: scrollerTarget, + start: `top ${startPct}%`, + once: true, + onEnter: () => tl.play() }); return () => { - ScrollTrigger.getAll().forEach(t => t.kill()); - gsap.killTweensOf(el); + st.kill(); + tl.kill(); }; }, [ - distance, - direction, - reverse, - duration, - ease, - initialOpacity, - animateOpacity, - scale, - threshold, - delay, - onComplete + container, + distance, direction, reverse, duration, ease, + initialOpacity, animateOpacity, scale, threshold, + delay, disappearAfter, disappearDuration, + disappearEase, onComplete, onDisappearanceComplete ]); - return
{children}
; + return ( +
+ {children} +
+ ); }; -export default AnimatedContent; +export default AnimatedContent; \ No newline at end of file diff --git a/src/tailwind/Animations/AnimatedContent/AnimatedContent.jsx b/src/tailwind/Animations/AnimatedContent/AnimatedContent.jsx index 244af1db..38999f04 100644 --- a/src/tailwind/Animations/AnimatedContent/AnimatedContent.jsx +++ b/src/tailwind/Animations/AnimatedContent/AnimatedContent.jsx @@ -6,6 +6,7 @@ gsap.registerPlugin(ScrollTrigger); const AnimatedContent = ({ children, + container, distance = 100, direction = 'vertical', reverse = false, @@ -16,7 +17,13 @@ const AnimatedContent = ({ scale = 1, threshold = 0.1, delay = 0, - onComplete + disappearAfter = 0, + disappearDuration = 0.5, + disappearEase = 'power3.in', + onComplete, + onDisappearanceComplete, + className = '', + ...props }) => { const ref = useRef(null); @@ -24,6 +31,12 @@ const AnimatedContent = ({ const el = ref.current; if (!el) return; + let scrollerTarget = container || document.getElementById('snap-main-container') || null; + + if (typeof scrollerTarget === 'string') { + scrollerTarget = document.querySelector(scrollerTarget); + } + const axis = direction === 'horizontal' ? 'x' : 'y'; const offset = reverse ? -distance : distance; const startPct = (1 - threshold) * 100; @@ -31,44 +44,66 @@ const AnimatedContent = ({ gsap.set(el, { [axis]: offset, scale, - opacity: animateOpacity ? initialOpacity : 1 + opacity: animateOpacity ? initialOpacity : 1, + visibility: 'visible' + }); + + const tl = gsap.timeline({ + paused: true, + delay, + onComplete: () => { + if (onComplete) onComplete(); + if (disappearAfter > 0) { + gsap.to(el, { + [axis]: reverse ? distance : -distance, + scale: 0.8, + opacity: animateOpacity ? initialOpacity : 0, + delay: disappearAfter, + duration: disappearDuration, + ease: disappearEase, + onComplete: () => onDisappearanceComplete?.() + }); + } + } }); - gsap.to(el, { + tl.to(el, { [axis]: 0, scale: 1, opacity: 1, duration, - ease, - delay, - onComplete, - scrollTrigger: { - trigger: el, - start: `top ${startPct}%`, - toggleActions: 'play none none none', - once: true - } + ease + }); + + const st = ScrollTrigger.create({ + trigger: el, + scroller: scrollerTarget, + start: `top ${startPct}%`, + once: true, + onEnter: () => tl.play() }); return () => { - ScrollTrigger.getAll().forEach(t => t.kill()); - gsap.killTweensOf(el); + st.kill(); + tl.kill(); }; }, [ - distance, - direction, - reverse, - duration, - ease, - initialOpacity, - animateOpacity, - scale, - threshold, - delay, - onComplete + container, + distance, direction, reverse, duration, ease, + initialOpacity, animateOpacity, scale, threshold, + delay, disappearAfter, disappearDuration, + disappearEase, onComplete, onDisappearanceComplete ]); - return
{children}
; + return ( +
+ {children} +
+ ); }; -export default AnimatedContent; +export default AnimatedContent; \ No newline at end of file diff --git a/src/ts-default/Animations/AnimatedContent/AnimatedContent.tsx b/src/ts-default/Animations/AnimatedContent/AnimatedContent.tsx index 781b22e8..616204c7 100644 --- a/src/ts-default/Animations/AnimatedContent/AnimatedContent.tsx +++ b/src/ts-default/Animations/AnimatedContent/AnimatedContent.tsx @@ -1,26 +1,32 @@ -import React, { useRef, useEffect, ReactNode } from 'react'; +import React, { useRef, useEffect } from 'react'; import { gsap } from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; gsap.registerPlugin(ScrollTrigger); -interface AnimatedContentProps { - children: ReactNode; +interface AnimatedContentProps extends React.HTMLAttributes { + children: React.ReactNode; + container?: Element | string | null; distance?: number; direction?: 'vertical' | 'horizontal'; reverse?: boolean; duration?: number; - ease?: string | ((progress: number) => number); + ease?: string; initialOpacity?: number; animateOpacity?: boolean; scale?: number; threshold?: number; delay?: number; + disappearAfter?: number; + disappearDuration?: number; + disappearEase?: string; onComplete?: () => void; + onDisappearanceComplete?: () => void; } const AnimatedContent: React.FC = ({ children, + container, distance = 100, direction = 'vertical', reverse = false, @@ -31,7 +37,14 @@ const AnimatedContent: React.FC = ({ scale = 1, threshold = 0.1, delay = 0, - onComplete + disappearAfter = 0, + disappearDuration = 0.5, + disappearEase = 'power3.in', + onComplete, + onDisappearanceComplete, + className = '', + style, + ...props }) => { const ref = useRef(null); @@ -39,6 +52,13 @@ const AnimatedContent: React.FC = ({ const el = ref.current; if (!el) return; + let scrollerTarget: Element | string | null = + container || document.getElementById('snap-main-container') || null; + + if (typeof scrollerTarget === 'string') { + scrollerTarget = document.querySelector(scrollerTarget); + } + const axis = direction === 'horizontal' ? 'x' : 'y'; const offset = reverse ? -distance : distance; const startPct = (1 - threshold) * 100; @@ -46,30 +66,52 @@ const AnimatedContent: React.FC = ({ gsap.set(el, { [axis]: offset, scale, - opacity: animateOpacity ? initialOpacity : 1 + opacity: animateOpacity ? initialOpacity : 1, + visibility: 'visible' + }); + + const tl = gsap.timeline({ + paused: true, + delay, + onComplete: () => { + if (onComplete) onComplete(); + + if (disappearAfter > 0) { + gsap.to(el, { + [axis]: reverse ? distance : -distance, + scale: 0.8, + opacity: animateOpacity ? initialOpacity : 0, + delay: disappearAfter, + duration: disappearDuration, + ease: disappearEase, + onComplete: () => onDisappearanceComplete?.() + }); + } + } }); - gsap.to(el, { + tl.to(el, { [axis]: 0, scale: 1, opacity: 1, duration, - ease, - delay, - onComplete, - scrollTrigger: { - trigger: el, - start: `top ${startPct}%`, - toggleActions: 'play none none none', - once: true - } + ease + }); + + const st = ScrollTrigger.create({ + trigger: el, + scroller: scrollerTarget || window, + start: `top ${startPct}%`, + once: true, + onEnter: () => tl.play() }); return () => { - ScrollTrigger.getAll().forEach(t => t.kill()); - gsap.killTweensOf(el); + st.kill(); + tl.kill(); }; }, [ + container, distance, direction, reverse, @@ -80,10 +122,23 @@ const AnimatedContent: React.FC = ({ scale, threshold, delay, - onComplete + disappearAfter, + disappearDuration, + disappearEase, + onComplete, + onDisappearanceComplete ]); - return
{children}
; + return ( +
+ {children} +
+ ); }; -export default AnimatedContent; +export default AnimatedContent; \ No newline at end of file diff --git a/src/ts-tailwind/Animations/AnimatedContent/AnimatedContent.tsx b/src/ts-tailwind/Animations/AnimatedContent/AnimatedContent.tsx index 781b22e8..96ef1a64 100644 --- a/src/ts-tailwind/Animations/AnimatedContent/AnimatedContent.tsx +++ b/src/ts-tailwind/Animations/AnimatedContent/AnimatedContent.tsx @@ -1,26 +1,32 @@ -import React, { useRef, useEffect, ReactNode } from 'react'; +import React, { useRef, useEffect } from 'react'; import { gsap } from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; gsap.registerPlugin(ScrollTrigger); -interface AnimatedContentProps { - children: ReactNode; +interface AnimatedContentProps extends React.HTMLAttributes { + children: React.ReactNode; + container?: Element | string | null; distance?: number; direction?: 'vertical' | 'horizontal'; reverse?: boolean; duration?: number; - ease?: string | ((progress: number) => number); + ease?: string; initialOpacity?: number; animateOpacity?: boolean; scale?: number; threshold?: number; delay?: number; + disappearAfter?: number; + disappearDuration?: number; + disappearEase?: string; onComplete?: () => void; + onDisappearanceComplete?: () => void; } const AnimatedContent: React.FC = ({ children, + container, distance = 100, direction = 'vertical', reverse = false, @@ -31,7 +37,13 @@ const AnimatedContent: React.FC = ({ scale = 1, threshold = 0.1, delay = 0, - onComplete + disappearAfter = 0, + disappearDuration = 0.5, + disappearEase = 'power3.in', + onComplete, + onDisappearanceComplete, + className = '', + ...props }) => { const ref = useRef(null); @@ -39,6 +51,13 @@ const AnimatedContent: React.FC = ({ const el = ref.current; if (!el) return; + let scrollerTarget: Element | string | null = + container || document.getElementById('snap-main-container') || null; + + if (typeof scrollerTarget === 'string') { + scrollerTarget = document.querySelector(scrollerTarget); + } + const axis = direction === 'horizontal' ? 'x' : 'y'; const offset = reverse ? -distance : distance; const startPct = (1 - threshold) * 100; @@ -46,44 +65,66 @@ const AnimatedContent: React.FC = ({ gsap.set(el, { [axis]: offset, scale, - opacity: animateOpacity ? initialOpacity : 1 + opacity: animateOpacity ? initialOpacity : 1, + visibility: 'visible' + }); + + const tl = gsap.timeline({ + paused: true, + delay, + onComplete: () => { + if (onComplete) onComplete(); + if (disappearAfter > 0) { + gsap.to(el, { + [axis]: reverse ? distance : -distance, + scale: 0.8, + opacity: animateOpacity ? initialOpacity : 0, + delay: disappearAfter, + duration: disappearDuration, + ease: disappearEase, + onComplete: () => onDisappearanceComplete?.() + }); + } + } }); - gsap.to(el, { + tl.to(el, { [axis]: 0, scale: 1, opacity: 1, duration, - ease, - delay, - onComplete, - scrollTrigger: { - trigger: el, - start: `top ${startPct}%`, - toggleActions: 'play none none none', - once: true - } + ease + }); + + const st = ScrollTrigger.create({ + trigger: el, + scroller: scrollerTarget || window, + start: `top ${startPct}%`, + once: true, + onEnter: () => tl.play() }); return () => { - ScrollTrigger.getAll().forEach(t => t.kill()); - gsap.killTweensOf(el); + st.kill(); + tl.kill(); }; }, [ - distance, - direction, - reverse, - duration, - ease, - initialOpacity, - animateOpacity, - scale, - threshold, - delay, - onComplete + container, + distance, direction, reverse, duration, ease, + initialOpacity, animateOpacity, scale, threshold, + delay, disappearAfter, disappearDuration, + disappearEase, onComplete, onDisappearanceComplete ]); - return
{children}
; + return ( +
+ {children} +
+ ); }; -export default AnimatedContent; +export default AnimatedContent; \ No newline at end of file