界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
效率与协作 · SKILL.md

gsap

gsap

【效率与协作】GSAP (GreenSock Animation Platform) — high-performance JavaScript animation engine with a plugin ecosystem. Covers tweens, easing, timelines, ScrollTrigger and the useGSAP React hook. USE WHEN: user mentions "GSAP", "GreenSock", "ScrollTrigger", "useGSAP", "timeline animation", "tween", asks about scroll-driven sequences or complex animation choreog…

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

name: gsap description: | GSAP (GreenSock Animation Platform) — high-performance JavaScript animation engine with a plugin ecosystem. Covers tweens, easing, timelines, ScrollTrigger and the useGSAP React hook.

USE WHEN: user mentions "GSAP", "GreenSock", "ScrollTrigger", "useGSAP", "timeline animation", "tween", asks about scroll-driven sequences or complex animation choreography

DO NOT USE FOR: React-idiomatic declarative animation (use framer-motion), SVG path morphing basics (use svg-animation), 3D scenes (use three-js) allowed-tools: Read, Grep, Glob, Write, Edit

GSAP Skill

GreenSock Animation Platform — high-performance JS animation engine with plugin ecosystem.

Install

npm install gsap
# Plugins (ScrollTrigger free, others require club membership):
# ScrollTrigger, Flip, Observer, ScrollSmoother — included in gsap package

Core API

import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { Flip } from "gsap/Flip";
gsap.registerPlugin(ScrollTrigger, Flip);
MethodPurpose
gsap.to(target, vars)Animate FROM current state TO vars
gsap.from(target, vars)Animate FROM vars TO current state
gsap.fromTo(target, from, to)Explicit start and end
gsap.set(target, vars)Instant set, no animation
gsap.timeline(vars)Sequence multiple tweens
gsap.context(fn, scope)Scope cleanup (React)
gsap.matchMedia()Responsive animations

Tween Properties

gsap.to(".box", {
  x: 100,           // translateX (px)
  y: -50,           // translateY
  rotation: 360,    // degrees
  scale: 1.5,
  opacity: 0,
  duration: 1,
  delay: 0.2,
  ease: "power2.out",
  stagger: 0.1,     // when targeting multiple elements
  repeat: -1,       // -1 = infinite
  yoyo: true,       // reverse on repeat
  onComplete: () => console.log("done"),
});

Easing Reference

EaseCharacter
power1-4.in/out/inOutPolynomial — power2.out is the go-to
elastic.out(1, 0.3)Springy bounce
back.out(1.7)Slight overshoot
bounce.outBall bounce
circ.outCircular — sharp deceleration
expo.outDramatic fast-to-slow
none / linearConstant speed

Timeline

const tl = gsap.timeline({ defaults: { ease: "power2.out", duration: 0.5 } });

tl.from(".hero-title",    { opacity: 0, y: 60 })
  .from(".hero-subtitle", { opacity: 0, y: 40 }, "-=0.3")   // 0.3s overlap
  .from(".hero-cta",      { opacity: 0, scale: 0.9 }, "+=0.1") // 0.1s gap
  .from(".hero-image",    { opacity: 0, x: 60 }, "<0.2");    // same start as prev + 0.2

// Position parameter:
// "<"   = same start as previous
// ">"   = end of previous
// "+=n" = n seconds after end
// "-=n" = n seconds before end
// "1.5" = absolute time in timeline

ScrollTrigger

gsap.to(".panel", {
  xPercent: -100 * (panels.length - 1),
  ease: "none",
  scrollTrigger: {
    trigger: ".scroll-container",
    pin: true,           // pins the trigger element during scroll
    scrub: 1,            // smooth scrubbing (lag in seconds)
    snap: 1 / (panels.length - 1),
    end: () => `+=${containerRef.current?.offsetWidth}`,
  }
});

// Callbacks
ScrollTrigger.create({
  trigger: "#section",
  start: "top 80%",
  end: "bottom 20%",
  onEnter: () => console.log("entered"),
  onLeave: () => console.log("left"),
  onEnterBack: () => console.log("entered back"),
  markers: process.env.NODE_ENV === "development", // visual debug markers
});

React Integration — useGSAP hook

import { useGSAP } from "@gsap/react";
import gsap from "gsap";
import { useRef } from "react";

gsap.registerPlugin(useGSAP);

function AnimatedHero() {
  const containerRef = useRef<HTMLDivElement>(null);

  useGSAP(() => {
    // All GSAP code here is automatically cleaned up on unmount
    gsap.from(".title", { opacity: 0, y: 60, duration: 0.8, ease: "power3.out" });
  }, { scope: containerRef }); // scope = only select within containerRef

  return (
    <div ref={containerRef}>
      <h1 className="title">Hello</h1>
    </div>
  );
}

Context (manual cleanup without useGSAP)

useEffect(() => {
  const ctx = gsap.context(() => {
    gsap.from(".item", { opacity: 0, stagger: 0.1 });
  }, containerRef);

  return () => ctx.revert(); // kills all tweens created in context
}, []);

Stagger

gsap.from(".card", {
  opacity: 0, y: 30,
  stagger: {
    amount: 0.6,         // total time spread across all elements
    from: "center",      // start: "start" | "end" | "center" | "random" | index
    ease: "power2.inOut",
    grid: [3, 4],        // for grid layouts
  }
});

SVG Path Draw (manual, no plugin)

function animatePath(el: SVGPathElement) {
  const len = el.getTotalLength();
  gsap.set(el, { strokeDasharray: len, strokeDashoffset: len });
  gsap.to(el, { strokeDashoffset: 0, duration: 2, ease: "power2.inOut" });
}

matchMedia (responsive)

const mm = gsap.matchMedia();

mm.add("(min-width: 768px)", () => {
  gsap.from(".title", { x: -100, opacity: 0 });
});

mm.add("(max-width: 767px)", () => {
  gsap.from(".title", { y: 40, opacity: 0 });
});

// Cleanup:
return () => mm.revert();

Reduced Motion

const prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

gsap.to(".element", {
  x: prefersReduced ? 0 : 200,
  duration: prefersReduced ? 0 : 1,
  opacity: 1,
});

Pitfalls

  • Always ctx.revert() or use useGSAP in React — GSAP tweens survive component unmount otherwise
  • scrub: true = hard sync with scroll; scrub: 1 = 1s lag (smoother)
  • pin: true — the trigger element must have explicit height for the pinned section to work
  • Avoid document.querySelector inside components — use refs with gsap.context(scope)
  • ScrollTrigger.refresh() after dynamic content loads (images, fonts)
我的收藏