gsap-react

安装量: 500
排名: #2132

安装

npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill gsap-react

GSAP React Integration

React-specific patterns for GSAP animations.

Quick Start npm install gsap @gsap/react

import { useGSAP } from '@gsap/react'; import gsap from 'gsap';

function Component() { const containerRef = useRef(null);

useGSAP(() => { gsap.to('.box', { x: 200, duration: 1 }); }, { scope: containerRef });

return (

Animated
); }

useGSAP Hook Basic Usage import { useGSAP } from '@gsap/react'; import gsap from 'gsap';

function AnimatedComponent() { const container = useRef(null);

useGSAP(() => { // All GSAP animations here gsap.from('.item', { opacity: 0, y: 50, stagger: 0.1 }); }, { scope: container }); // Scope limits selector queries

return (

Item 1
Item 2
Item 3
); }

With Dependencies function AnimatedComponent({ isOpen }) { const container = useRef(null);

useGSAP(() => { gsap.to('.drawer', { height: isOpen ? 'auto' : 0, duration: 0.3 }); }, { scope: container, dependencies: [isOpen] });

return (

Content
); }

Returning Context function Component() { const container = useRef(null);

const { context, contextSafe } = useGSAP(() => { gsap.to('.box', { x: 200 }); }, { scope: container });

// Use contextSafe for event handlers const handleClick = contextSafe(() => { gsap.to('.box', { rotation: 360 }); });

return (

Click me
); }

Ref Patterns Single Element Ref function SingleElement() { const boxRef = useRef(null);

useGSAP(() => { gsap.to(boxRef.current, { x: 200, rotation: 360, duration: 1 }); });

return

Box
; }

Multiple Element Refs function MultipleElements() { const itemsRef = useRef([]);

useGSAP(() => { gsap.from(itemsRef.current, { opacity: 0, y: 30, stagger: 0.1 }); });

return (

{[1, 2, 3].map((item, i) => (
itemsRef.current[i] = el} > Item {item}
))}
); }

Dynamic Refs function DynamicList({ items }) { const itemsRef = useRef(new Map());

useGSAP(() => { gsap.from(Array.from(itemsRef.current.values()), { opacity: 0, y: 20, stagger: 0.05 }); }, { dependencies: [items.length] });

return (

{items.map(item => (
{ if (el) itemsRef.current.set(item.id, el); else itemsRef.current.delete(item.id); }} > {item.name}
))}
); }

Context and Cleanup Automatic Cleanup // useGSAP automatically cleans up animations on unmount function Component() { useGSAP(() => { // This timeline is automatically killed on unmount gsap.timeline() .to('.a', { x: 100 }) .to('.b', { x: 100 }); }); }

Manual Context (Without useGSAP) import gsap from 'gsap';

function Component() { useEffect(() => { const ctx = gsap.context(() => { gsap.to('.box', { x: 200 }); gsap.to('.circle', { rotation: 360 }); });

return () => ctx.revert(); // Cleanup

}, []); }

Scoped Context function Component() { const containerRef = useRef(null);

useEffect(() => { const ctx = gsap.context(() => { // Selectors only query within containerRef gsap.to('.item', { opacity: 1 }); }, containerRef);

return () => ctx.revert();

}, []); }

Event Handlers contextSafe for Events function InteractiveComponent() { const container = useRef(null);

const { contextSafe } = useGSAP(() => { // Initial animation gsap.set('.box', { scale: 1 }); }, { scope: container });

const handleMouseEnter = contextSafe(() => { gsap.to('.box', { scale: 1.1, duration: 0.2 }); });

const handleMouseLeave = contextSafe(() => { gsap.to('.box', { scale: 1, duration: 0.2 }); });

return (

Hover me
); }

useCallback Alternative function Component() { const boxRef = useRef(null); const tweenRef = useRef(null);

const animateBox = useCallback(() => { tweenRef.current?.kill(); tweenRef.current = gsap.to(boxRef.current, { x: '+=50', duration: 0.3 }); }, []);

useEffect(() => { return () => tweenRef.current?.kill(); }, []);

return

Click
; }

Timeline Management Timeline Ref Pattern function TimelineComponent() { const container = useRef(null); const tl = useRef(null);

useGSAP(() => { tl.current = gsap.timeline({ paused: true }) .to('.box', { x: 200 }) .to('.box', { y: 100 }) .to('.box', { rotation: 360 }); }, { scope: container });

const play = () => tl.current?.play(); const reverse = () => tl.current?.reverse(); const restart = () => tl.current?.restart();

return (

Animated
); }

Controlled Timeline function ControlledAnimation({ progress }) { const container = useRef(null); const tl = useRef(null);

useGSAP(() => { tl.current = gsap.timeline({ paused: true }) .to('.element', { x: 500 }) .to('.element', { y: 200 }); }, { scope: container });

// Update timeline progress when prop changes useEffect(() => { if (tl.current) { tl.current.progress(progress); } }, [progress]);

return (

Controlled
); }

ScrollTrigger in React Basic ScrollTrigger import { useGSAP } from '@gsap/react'; import gsap from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

function ScrollComponent() { const container = useRef(null);

useGSAP(() => { gsap.from('.section', { opacity: 0, y: 100, scrollTrigger: { trigger: '.section', start: 'top 80%', toggleActions: 'play none none none' } }); }, { scope: container });

return (

Scroll to reveal
); }

ScrollTrigger Cleanup function ScrollComponent() { const container = useRef(null);

useGSAP(() => { const triggers = [];

gsap.utils.toArray('.item').forEach(item => {
  const trigger = ScrollTrigger.create({
    trigger: item,
    start: 'top 80%',
    onEnter: () => gsap.to(item, { opacity: 1 })
  });
  triggers.push(trigger);
});

// Return cleanup function
return () => triggers.forEach(t => t.kill());

}, { scope: container }); }

Custom Hooks useAnimation Hook function useAnimation(animation, deps = []) { const elementRef = useRef(null); const tweenRef = useRef(null);

useGSAP(() => { if (elementRef.current) { tweenRef.current = animation(elementRef.current); } return () => tweenRef.current?.kill(); }, { dependencies: deps });

return elementRef; }

// Usage function Component() { const boxRef = useAnimation((el) => gsap.from(el, { opacity: 0, y: 50, duration: 0.5 }) );

return

Animated
; }

useFadeIn Hook function useFadeIn(options = {}) { const { duration = 0.5, delay = 0, y = 30 } = options; const ref = useRef(null);

useGSAP(() => { gsap.from(ref.current, { opacity: 0, y, duration, delay, ease: 'power2.out' }); });

return ref; }

// Usage function Card() { const cardRef = useFadeIn({ delay: 0.2 }); return

Card content
; }

useHoverAnimation Hook function useHoverAnimation(enterAnimation, leaveAnimation) { const ref = useRef(null); const { contextSafe } = useGSAP({ scope: ref });

const onEnter = contextSafe(() => enterAnimation(ref.current)); const onLeave = contextSafe(() => leaveAnimation(ref.current));

return { ref, onMouseEnter: onEnter, onMouseLeave: onLeave }; }

// Usage function Button() { const hoverProps = useHoverAnimation( (el) => gsap.to(el, { scale: 1.05, duration: 0.2 }), (el) => gsap.to(el, { scale: 1, duration: 0.2 }) );

return ; }

Temporal Collapse Patterns Animated Countdown Digit function CountdownDigit({ value, label }) { const digitRef = useRef(null); const prevValue = useRef(value);

useGSAP(() => { if (prevValue.current !== value) { gsap.timeline() .to(digitRef.current, { rotationX: -90, opacity: 0, duration: 0.25, ease: 'power2.in' }) .call(() => { digitRef.current.textContent = value; prevValue.current = value; }) .fromTo(digitRef.current, { rotationX: 90, opacity: 0 }, { rotationX: 0, opacity: 1, duration: 0.25, ease: 'power2.out' } ); } }, { dependencies: [value] });

return (

{value} {label}
); }

Cosmic Pulse Effect function CosmicPulse({ children, color = '#00F5FF' }) { const containerRef = useRef(null);

useGSAP(() => { gsap.to(containerRef.current, { boxShadow: 0 0 30px ${color}, 0 0 60px ${color}, duration: 1, repeat: -1, yoyo: true, ease: 'sine.inOut' }); }, { scope: containerRef });

return

{children}
; }

Performance Tips // 1. Use will-change for heavy animations gsap.set('.animated', { willChange: 'transform' });

// 2. Batch similar animations useGSAP(() => { gsap.to('.item', { opacity: 1, stagger: 0.1 }); // Single tween // Not: items.forEach(item => gsap.to(item, ...)) // Multiple tweens });

// 3. Use refs over selectors for frequently animated elements const boxRef = useRef(null); gsap.to(boxRef.current, { x: 100 }); // Faster

// 4. Kill animations on rapid state changes const tweenRef = useRef(null); useEffect(() => { tweenRef.current?.kill(); tweenRef.current = gsap.to(...); }, [dependency]);

Reference See gsap-fundamentals for animation basics See gsap-sequencing for timeline composition See gsap-scrolltrigger for scroll-based animations

返回排行榜