mcpField
G
gsap-svg

gsap-svg

github.com/iotronDesign & UI939 installsUpdated 31w ago
Repository

About gsap-svg

gsap-svg is a skill for developers creating SVG animations with GSAP in Vue or Nuxt. It covers path drawing, morphing, and layered effects, with implementation notes on animation ownership and SVG cleanup.

Key features

  1. 01SVG path drawing with strokeDashoffset
  2. 02DrawSVG plugin examples
  3. 03SVG path morphing
  4. 04Scroll-triggered animations
  5. 05Staggered waves and pulse rings
  6. 06SVG cleanup and animation guidance

Use cases

  1. 01Animate an SVG path being drawn
  2. 02Morph a path during scrolling
  3. 03Sequence SVG paths and circles
  4. 04Build a repeating pulse ring

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/iotron/gsap-cookbook --skill gsap-svg

After installing, type/gsap-svgin Claude Code to confirm it loaded.

Bundled filesreferences/svg-patterns.md

Details

From the project README

GSAP SVG — Vue / Nuxt Patterns

Flow: gsap-setup → gsap-animate → gsap-svg → gsap-optimise → gsap-test

Companion: For DrawSVG/MorphSVG API reference, invoke gsap-plugins. This skill covers SVG animation recipes only. Requires: greensock/gsap-skills


1. SVG Path Drawing (strokeDashoffset)

Manual approach
const ctx = gsap.context(() => {
  const paths = containerRef.value.querySelectorAll('path')
  paths.forEach((path) => {
    const len = path.getTotalLength()
    gsap.set(path, { strokeDasharray: len, strokeDashoffset: len })
  })
  gsap.to(paths, {
    strokeDashoffset: 0, duration: 2, ease: 'power2.inOut',
    stagger: { each: 0.08, from: 'start' },
  })
}, containerRef.value)
With DrawSVG plugin (lazy-loaded)
await $lazyLoadDrawSVG()
gsap.from(paths, { drawSVG: '0%', duration: 2, stagger: 0.05 })
gsap.to(paths, { drawSVG: '40% 80%', duration: 1.5 }) // partial range
Staggered paths then nodes
const tl = gsap.timeline()
tl.to(paths, { strokeDashoffset: 0, duration: 1.5, ease: 'power2.inOut', stagger: { each: 0.05 } })
  .from(circles, { scale: 0, autoAlpha: 0, duration: 0.6, ease: 'back.out(2)',
    stagger: { each: 0.03, from: 'random' } }, '-=0.5')
Infinite pulse ring
gsap.fromTo(ringEl,
  { scale: 1, autoAlpha: 0.7 },
  { scale: 2.2, autoAlpha: 0, duration: 2, ease: 'power1.out', repeat: -1, force3D: true }
)

2. SVG Morphing (MorphSVGPlugin)

const pathTo = pathEl.value.dataset.pathTo
gsap.to(pathEl.value, { attr: { d: pathTo }, duration: 1.5, ease: 'power2.inOut' })

// Scroll-driven
gsap.to(pathEl.value, {
  attr: { d: pathTo }, ease: 'none',
  scrollTrigger: { trigger: sectionRef.value, start: 'top center', end: 'bottom center', scrub: 0.5 },
})

// With MorphSVGPlugin
await $lazyLoadMorphSVG()
gsap.to(pathEl.value, { morphSVG: targetPathEl.value, duration: 1.5 })

3. Scallop Wave

gsap.from(ellipses, {
  scale: 0, autoAlpha: 0, transformOrigin: 'top center',
  duration: 0.8, ease: 'back.out(3)', force3D: true,
  stagger: { each: 0.04, from: 'center' },
  scrollTrigger: { trigger: containerRef.value, start: 'top 80%', toggleActions: 'play none none reverse' },
})

4. Critical Gotchas

fill: transparent NOT fill: none

none means "unpainted" — GSAP cannot interpolate from it. Use transparent.

Separate animation concern ownership

Concurrent timelines must own different properties. Wave owns stroke. Color owns fill + autoAlpha.

Absolute timeline positioning

Use .add(animation, timeInSeconds) not relative offsets for multi-layer compositions.

SVG DOM cleanup
onUnmounted(() => {
  ctx?.revert()
  circuitWrap.value?.replaceChildren() // clear SVG DOM
})

References

  • references/svg-patterns.md — Circuit Tree triple-layer animation, CTAHud 5-layer system, Dynamic Morphing shape overlays, Smooth Morph with interpolation

Comments

Markdown supported