gsap

安装量: 757
排名: #1624

安装

npx skills add https://github.com/martinholovsky/claude-skills-generator --skill gsap
GSAP Animation Skill
File Organization
This skill uses split structure. See
references/
for advanced patterns.
1. Overview
This skill provides GSAP (GreenSock Animation Platform) expertise for creating smooth, professional animations in the JARVIS AI Assistant HUD.
Risk Level
LOW - Animation library with minimal security surface
Primary Use Cases
:
HUD panel entrance/exit animations
Status indicator transitions
Data visualization animations
Scroll-triggered effects
Complex timeline sequences
2. Core Responsibilities
2.1 Fundamental Principles
TDD First
Write animation tests before implementation
Performance Aware
Use transforms/opacity for GPU acceleration, avoid layout thrashing
Cleanup Required
Always kill animations on component unmount
Timeline Organization
Use timelines for complex sequences
Easing Selection
Choose appropriate easing for HUD feel
Accessibility
Respect reduced motion preferences
Memory Management
Avoid memory leaks with proper cleanup 2.5 Implementation Workflow (TDD) Step 1: Write Failing Test First // tests/animations/panel-animation.test.ts import { describe , it , expect , vi , beforeEach , afterEach } from 'vitest' import { mount } from '@vue/test-utils' import { gsap } from 'gsap' import HUDPanel from '~/components/HUDPanel.vue' describe ( 'HUDPanel Animation' , ( ) => { beforeEach ( ( ) => { // Mock reduced motion Object . defineProperty ( window , 'matchMedia' , { writable : true , value : vi . fn ( ) . mockImplementation ( query => ( { matches : false , media : query } ) ) } ) } ) afterEach ( ( ) => { // Verify cleanup gsap . globalTimeline . clear ( ) } ) it ( 'animates panel entrance with correct properties' , async ( ) => { const wrapper = mount ( HUDPanel ) // Wait for animation to complete await new Promise ( resolve => setTimeout ( resolve , 600 ) ) const panel = wrapper . find ( '.hud-panel' ) expect ( panel . exists ( ) ) . toBe ( true ) } ) it ( 'cleans up animations on unmount' , async ( ) => { const wrapper = mount ( HUDPanel ) const childCount = gsap . globalTimeline . getChildren ( ) . length await wrapper . unmount ( ) // All animations should be killed expect ( gsap . globalTimeline . getChildren ( ) . length ) . toBeLessThan ( childCount ) } ) it ( 'respects reduced motion preference' , async ( ) => { // Mock reduced motion enabled window . matchMedia = vi . fn ( ) . mockImplementation ( ( ) => ( { matches : true } ) ) const wrapper = mount ( HUDPanel ) const panel = wrapper . find ( '.hud-panel' ) . element // Should set final state immediately without animation expect ( gsap . getProperty ( panel , 'opacity' ) ) . toBe ( 1 ) } ) } ) Step 2: Implement Minimum to Pass // components/HUDPanel.vue - implement animation logic const animation = ref < gsap . core . Tween | null

( null ) onMounted ( ( ) => { if ( ! panelRef . value ) return if ( window . matchMedia ( '(prefers-reduced-motion: reduce)' ) . matches ) { gsap . set ( panelRef . value , { opacity : 1 } ) return } animation . value = gsap . from ( panelRef . value , { opacity : 0 , y : 20 , duration : 0.5 } ) } ) onUnmounted ( ( ) => { animation . value ?. kill ( ) } ) Step 3: Refactor Following Patterns // Extract to composable for reusability export function usePanelAnimation ( elementRef : Ref < HTMLElement | null

) { const animation = ref < gsap . core . Tween | null

( null ) const animate = ( ) => { if ( ! elementRef . value ) return if ( window . matchMedia ( '(prefers-reduced-motion: reduce)' ) . matches ) { gsap . set ( elementRef . value , { opacity : 1 } ) return } animation . value = gsap . from ( elementRef . value , { opacity : 0 , y : 20 , duration : 0.5 , ease : 'power2.out' } ) } onMounted ( animate ) onUnmounted ( ( ) => animation . value ?. kill ( ) ) return { animation } } Step 4: Run Full Verification

Run animation tests

npm test -- --grep "Animation"

Check for memory leaks

npm run test:memory

Verify 60fps performance

npm run test:performance 3. Technology Stack & Versions 3.1 Recommended Versions Package Version Notes gsap ^3.12.0 Core library @gsap/vue ^3.12.0 Vue integration ScrollTrigger included Scroll effects 3.2 Vue Integration // plugins/gsap.ts import { gsap } from 'gsap' import { ScrollTrigger } from 'gsap/ScrollTrigger' export default defineNuxtPlugin ( ( ) => { gsap . registerPlugin ( ScrollTrigger ) return { provide : { gsap , ScrollTrigger } } } ) 4. Implementation Patterns 4.1 Panel Entrance Animation

4.2 Status Indicator Animation // composables/useStatusAnimation.ts import { gsap } from 'gsap' export function useStatusAnimation ( element : Ref < HTMLElement | null

) { const timeline = ref < gsap . core . Timeline | null

( null ) const animateStatus = ( status : string ) => { if ( ! element . value ) return timeline . value ?. kill ( ) timeline . value = gsap . timeline ( ) switch ( status ) { case 'active' : timeline . value . to ( element . value , { scale : 1.2 , duration : 0.2 , ease : 'power2.out' } ) . to ( element . value , { scale : 1 , duration : 0.3 , ease : 'elastic.out(1, 0.3)' } ) break case 'warning' : timeline . value . to ( element . value , { backgroundColor : '#f59e0b' , boxShadow : '0 0 10px #f59e0b' , duration : 0.3 , repeat : 2 , yoyo : true } ) break case 'error' : timeline . value . to ( element . value , { x : - 5 , duration : 0.05 , repeat : 5 , yoyo : true } ) break } } onUnmounted ( ( ) => { timeline . value ?. kill ( ) } ) return { animateStatus } } 4.3 Data Visualization Animation

4.4 Timeline Sequence // Create complex HUD startup sequence export function createStartupSequence ( elements : { logo : HTMLElement panels : HTMLElement [ ] status : HTMLElement } ) : gsap . core . Timeline { const tl = gsap . timeline ( { defaults : { ease : 'power2.out' } } ) // Logo reveal tl . from ( elements . logo , { opacity : 0 , scale : 0 , duration : 0.8 , ease : 'back.out(1.7)' } ) // Panels stagger in tl . from ( elements . panels , { opacity : 0 , x : - 30 , stagger : 0.1 , duration : 0.5 } , '-=0.3' ) // Status indicator tl . from ( elements . status , { opacity : 0 , y : 10 , duration : 0.3 } , '-=0.2' ) return tl } 4.5 Scroll-Triggered Animation

  1. Quality Standards 5.1 Performance // ✅ GOOD - Use transforms for GPU acceleration gsap . to ( element , { x : 100 , y : 50 , rotation : 45 , scale : 1.2 } ) // ❌ BAD - Triggers layout recalculation gsap . to ( element , { left : 100 , top : 50 , width : '120%' } ) 5.2 Accessibility // ✅ Respect reduced motion const prefersReducedMotion = window . matchMedia ( '(prefers-reduced-motion: reduce)' ) . matches if ( prefersReducedMotion ) { gsap . set ( element , { opacity : 1 } ) } else { gsap . from ( element , { opacity : 0 , duration : 0.5 } ) }
  2. Performance Patterns 6.1 will-change Property Usage // Good: Apply will-change before animation const animatePanel = ( element : HTMLElement ) => { element . style . willChange = 'transform, opacity' gsap . to ( element , { x : 100 , opacity : 0.8 , duration : 0.5 , onComplete : ( ) => { element . style . willChange = 'auto' } } ) } // Bad: Never removing will-change const animatePanelBad = ( element : HTMLElement ) => { element . style . willChange = 'transform, opacity' // Memory leak! gsap . to ( element , { x : 100 , opacity : 0.8 } ) } 6.2 Transform vs Layout Properties // Good: Use transforms (GPU accelerated) gsap . to ( element , { x : 100 , // translateX y : 50 , // translateY scale : 1.2 , // scale rotation : 45 , // rotate opacity : 0.5 // opacity } ) // Bad: Layout-triggering properties (CPU, causes reflow) gsap . to ( element , { left : 100 , // Triggers layout top : 50 , // Triggers layout width : '120%' , // Triggers layout height : 200 , // Triggers layout margin : 10 // Triggers layout } ) 6.3 Timeline Reuse // Good: Reuse timeline instance const timeline = gsap . timeline ( { paused : true } ) timeline . to ( element , { opacity : 1 , duration : 0.3 } ) . to ( element , { y : - 20 , duration : 0.5 } ) // Play/reverse as needed const show = ( ) => timeline . play ( ) const hide = ( ) => timeline . reverse ( ) // Bad: Creating new timeline each time const showBad = ( ) => { gsap . timeline ( ) . to ( element , { opacity : 1 , duration : 0.3 } ) . to ( element , { y : - 20 , duration : 0.5 } ) } 6.4 ScrollTrigger Batching // Good: Batch ScrollTrigger animations ScrollTrigger . batch ( '.animate-item' , { onEnter : ( elements ) => { gsap . to ( elements , { opacity : 1 , y : 0 , stagger : 0.1 , overwrite : true } ) } , onLeave : ( elements ) => { gsap . to ( elements , { opacity : 0 , y : - 20 , overwrite : true } ) } } ) // Bad: Individual ScrollTrigger per element document . querySelectorAll ( '.animate-item' ) . forEach ( item => { gsap . to ( item , { scrollTrigger : { trigger : item , start : 'top 80%' } , opacity : 1 , y : 0 } ) } ) 6.5 Lazy Initialization // Good: Initialize animations only when needed let panelAnimation : gsap . core . Timeline | null = null const getPanelAnimation = ( ) => { if ( ! panelAnimation ) { panelAnimation = gsap . timeline ( { paused : true } ) . from ( '.panel' , { opacity : 0 , y : 20 } ) . from ( '.panel-content' , { opacity : 0 , stagger : 0.1 } ) } return panelAnimation } const showPanel = ( ) => getPanelAnimation ( ) . play ( ) const hidePanel = ( ) => getPanelAnimation ( ) . reverse ( ) // Bad: Initialize all animations on mount onMounted ( ( ) => { // Creates timeline even if never used const animation1 = gsap . timeline ( ) . to ( '.panel1' , { x : 100 } ) const animation2 = gsap . timeline ( ) . to ( '.panel2' , { y : 100 } ) const animation3 = gsap . timeline ( ) . to ( '.panel3' , { scale : 1.2 } ) } )
  3. Testing & Quality 7.1 Animation Testing describe ( 'Panel Animation' , ( ) => { it ( 'cleans up on unmount' , async ( ) => { const wrapper = mount ( HUDPanel ) await wrapper . unmount ( ) // No active GSAP animations should remain expect ( gsap . globalTimeline . getChildren ( ) . length ) . toBe ( 0 ) } ) } )
  4. Common Mistakes & Anti-Patterns 8.1 Critical Anti-Patterns Never: Skip Cleanup // ❌ MEMORY LEAK onMounted ( ( ) => { gsap . to ( element , { x : 100 , duration : 1 } ) } ) // ✅ PROPER CLEANUP let tween : gsap . core . Tween onMounted ( ( ) => { tween = gsap . to ( element , { x : 100 , duration : 1 } ) } ) onUnmounted ( ( ) => { tween ?. kill ( ) } ) Never: Animate Layout Properties // ❌ BAD - Causes layout thrashing gsap . to ( element , { width : 200 , height : 100 } ) // ✅ GOOD - Use transforms gsap . to ( element , { scaleX : 2 , scaleY : 1 } )
  5. Pre-Implementation Checklist Phase 1: Before Writing Code Write failing tests for animation behavior Define animation timing and easing requirements Identify elements that need will-change hints Plan cleanup strategy for all animations Check if reduced motion support is needed Phase 2: During Implementation Use transforms/opacity only (no layout properties) Store animation references for cleanup Apply will-change before, remove after animation Use timelines for sequences Batch ScrollTrigger animations Implement lazy initialization for complex animations Phase 3: Before Committing All tests pass (npm test -- --grep "Animation") All animations cleaned up on unmount Reduced motion preference respected No memory leaks (check with DevTools) 60fps maintained (test with performance monitor) ScrollTrigger instances properly killed
  6. Summary
    GSAP provides professional animations for JARVIS HUD:
    Cleanup
    Always kill animations on unmount
    Performance
    Use transforms and opacity only
    Accessibility
    Respect reduced motion preference
    Organization
    Use timelines for sequences
    Remember
    Every animation must be cleaned up to prevent memory leaks. References : references/advanced-patterns.md
  7. Complex animation patterns
返回排行榜