bygreensock· 8 skills
Official GSAP skill for GSAP plugins — registration, ScrollToPlugin, ScrollSmoother, Flip, Draggable, Inertia, Observer, SplitText, ScrambleText, SVG and physics plugins, CustomEase, EasePack, CustomWiggle, CustomBounce, GSDevTools. Use when the user asks about a GSAP plugin, scroll-to, flip animations, draggable, SVG drawing, or plugin registration.
$npx -y skills add greensock/gsap-skills --skill gsap-pluginsInstalls into the current project.
Run `npx skills use "https://github.com/greensock/gsap-skills" --skill "greensock/gsap-skills/gsap-plugins"` and follow the generated skill instructions now. Read its complete output, redirecting it to a temporary file first if necessary. Resolve relative paths from the supporting-files directory it provides.
Use the skills in "https://github.com/greensock/gsap-skills" that are relevant to the current task. Run `npx skills add "https://github.com/greensock/gsap-skills"` and select the relevant skills, then follow their instructions.
| 1 | # GSAP Plugins |
| 2 | |
| 3 | ## When to Use This Skill |
| 4 | |
| 5 | Apply when using or reviewing code that uses GSAP plugins: registering plugins, scroll-to, flip/FLIP animations, draggable elements, SVG (DrawSVG, MorphSVG, MotionPath), text (SplitText, ScrambleText), physics, easing plugins (CustomEase, EasePack, CustomWiggle, CustomBounce), or GSDevTools. ScrollTrigger has its own skill (gsap-scrolltrigger). |
| 6 | |
| 7 | **Related skills:** For core tweens use **gsap-core**; for ScrollTrigger use **gsap-scrolltrigger**; for React use **gsap-react**. |
| 8 | |
| 9 | ## Licensing & Install (important) |
| 10 | |
| 11 | Every GSAP plugin is **free**, including for commercial use. Since [Webflow's acquisition of GSAP](https://gsap.com/blog/webflow-GSAP/), Club GSAP is no longer a paid tier and **no plugin requires a membership, license key, or auth token** — this includes formerly Club-only plugins (**SplitText**, **MorphSVG**, etc.). |
| 12 | |
| 13 | - ✅ Install everything from the public `gsap` npm package: `npm install gsap`. All plugins are included — import them as `gsap/SplitText`, `gsap/MorphSVGPlugin`, etc. |
| 14 | - ❌ Do **not** generate an `.npmrc` with a GreenSock auth token, suggest the private `npm.greensock.com` registry, or tell users to sign up for Club GSAP to access a plugin. Those instructions are outdated. |
| 15 | |
| 16 | ## Registering Plugins |
| 17 | |
| 18 | Register each plugin once so GSAP (and bundlers) know to include it. Use **gsap.registerPlugin()** with every plugin used in the project: |
| 19 | |
| 20 | ```javascript |
| 21 | import gsap from "gsap"; |
| 22 | import { ScrollToPlugin } from "gsap/ScrollToPlugin"; |
| 23 | import { Flip } from "gsap/Flip"; |
| 24 | import { Draggable } from "gsap/Draggable"; |
| 25 | |
| 26 | gsap.registerPlugin(ScrollToPlugin, Flip, Draggable); |
| 27 | ``` |
| 28 | |
| 29 | - ✅ Register before using the plugin in any tween or API call. |
| 30 | - ✅ In React, register at top level or once in the app (e.g. before first useGSAP); do not register inside a component that re-renders. useGSAP is a plugin that needs to be registered before use. |
| 31 | |
| 32 | ## Scroll |
| 33 | |
| 34 | ### ScrollToPlugin |
| 35 | |
| 36 | Animates scroll position (window or a scrollable element). Use for “scroll to element” or “scroll to position” without ScrollTrigger. |
| 37 | |
| 38 | ```javascript |
| 39 | gsap.registerPlugin(ScrollToPlugin); |
| 40 | |
| 41 | gsap.to(window, { duration: 1, scrollTo: { y: 500 } }); |
| 42 | gsap.to(window, { duration: 1, scrollTo: { y: "#section", offsetY: 50 } }); |
| 43 | gsap.to(scrollContainer, { duration: 1, scrollTo: { x: "max" } }); |
| 44 | ``` |
| 45 | |
| 46 | **ScrollToPlugin — key config (scrollTo object):** |
| 47 | |
| 48 | | Option | Description | |
| 49 | |--------|-------------| |
| 50 | | `x`, `y` | Target scroll position (number), or `"max"` for maximum | |
| 51 | | `element` | Selector or element to scroll to (for scroll-into-view) | |
| 52 | | `offsetX`, `offsetY` | Offset in pixels from the target position | |
| 53 | |
| 54 | ### ScrollSmoother |
| 55 | |
| 56 | Smooth scroll wrapper (smooths native scroll). Requires ScrollTrigger and a specific DOM structure (content wrapper + smooth wrapper). Use when smooth, momentum-style scroll is needed. See GSAP docs for setup; register after ScrollTrigger. DOM structure would look like: |
| 57 | |
| 58 | ```html |
| 59 | <body> |
| 60 | <div id="smooth-wrapper"> |
| 61 | <div id="smooth-content"> |
| 62 | <!--- ALL YOUR CONTENT HERE ---> |
| 63 | </div> |
| 64 | </div> |
| 65 | <!-- position: fixed elements can go outside ---> |
| 66 | </body> |
| 67 | ``` |
| 68 | |
| 69 | ## DOM / UI |
| 70 | |
| 71 | ### Flip |
| 72 | |
| 73 | Capture state with `Flip.getState()`, then apply changes (e.g. layout or class changes), then use `Flip.from()` to animate from the previous state to the new state (FLIP: First, Last, Invert, Play). Use when animating between two layout states (lists, grids, expanded/collapsed). |
| 74 | |
| 75 | ```javascript |
| 76 | gsap.registerPlugin(Flip); |
| 77 | |
| 78 | const state = Flip.getState(".item"); |
| 79 | // change DOM (reorder, add/remove, change classes) |
| 80 | Flip.from(state, { duration: 0.5, ease: "power2.inOut" }); |
| 81 | ``` |
| 82 | |
| 83 | **Flip — key config (Flip.from vars):** |
| 84 | |
| 85 | | Option | Description | |
| 86 | |--------|-------------| |
| 87 | | `absolute` | Use `position: absolute` during the flip (default: `false`) | |
| 88 | | `nested` | When true, only the first level of children is measured (better for nested transforms) | |
| 89 | | `scale` | When true, scale elements to fit (avoids stretch); default `true` | |
| 90 | | `simple` | When true, only position/scale are animated (faster, less accurate) | |
| 91 | | `duration`, `ease` | Standard tween options | |
| 92 | |
| 93 | #### More information |
| 94 | |
| 95 | https://gsap.com/docs/v3/Plugins/Flip |
| 96 | |
| 97 | ### Draggable |
| 98 | |
| 99 | Makes elements draggable, spinnable, or throwable with mouse/touch. Use for sliders, cards, reorderable lists, or any drag interaction. |
| 100 | |
| 101 | ```javascript |
| 102 | gsap.registerPlugin(Draggable, InertiaPlugin); |
| 103 | |
| 104 | Draggable.create(".box", { type: "x,y", bounds: "#container", inertia: true }); |
| 105 | Draggable.create(".knob", { type: "rotation" }); |
| 106 | ``` |
| 107 | |
| 108 | **Draggable — key config options:** |
| 109 | |
| 110 | | Option | Description | |
| 111 | |--------|-------------| |
| 112 | | `type` | `"x"`, `"y"`, `"x,y"`, `"rotation"`, `"scroll"` | |
| 113 | | `bounds` | Element, selector, or `{ minX, maxX, minY, maxY }` to constrain drag | |
| 114 | | `inertia` | `true` to enable throw/momentum (requires InertiaPlugin) | |
| 115 | | `edgeResistance` | 0–1; resistance when dragging past bounds | |
| 116 | | `cursor` | CSS cursor during drag | |
| 117 | | `onDragStart`, `onDrag`, `onDragEnd` | Callbacks; receive event and target | |
| 118 | | `onThrowUpdate`, `onThrowComplete` | Callbacks when inertia is active | |
| 119 | |
| 120 | ### Inertia (InertiaPlugin) |
| 121 | |
| 122 | Works with Draggable for momentum after release, or track the inertia/velocity of any property of any object so that it can then seamlessly glide to a stop using a simple tween. Register with Draggable when using `inertia: true`: |
| 123 | |
| 124 | ```javascript |
| 125 | gsap.registerPlugin(Draggable, InertiaPlugin); |
| 126 | Draggable.create(".box", { type: "x,y", inertia: true }); |
| 127 | ``` |
| 128 | |
| 129 | Or track velocity of a property: |
| 130 | ```javascript |
| 131 | InertiaPlugin.track(".box", "x"); |
| 132 | ``` |
| 133 | |
| 134 | Then use `"auto"` to continue the current velocity and glide to a stop: |
| 135 | |
| 136 | ```javascript |
| 137 | gsap.to(obj, { inertia: { x: "auto" } }); |
| 138 | ``` |
| 139 | |
| 140 | ### Observer |
| 141 | |
| 142 | Normalizes pointer and scroll input across devices. Use for swipe, scroll direction, or custom gesture logic without tying directly to scroll position like ScrollTrigger. |
| 143 | |
| 144 | ```javascript |
| 145 | gsap.registerPlugin(Observer); |
| 146 | |
| 147 | Observer.create({ |
| 148 | target: "#area", |
| 149 | onUp: () => {}, |
| 150 | onDown: () => {}, |
| 151 | onLeft: () => {}, |
| 152 | onRight: () => {}, |
| 153 | tolerance: 10 |
| 154 | }); |
| 155 | ``` |
| 156 | |
| 157 | **Observer — key config options:** |
| 158 | |
| 159 | | Option | Description | |
| 160 | |--------|-------------| |
| 161 | | `target` | Element or selector to observe | |
| 162 | | `onUp`, `onDown`, `onLeft`, `onRight` | Callbacks when swipe/scroll passes tolerance in that direction | |
| 163 | | `tolerance` | Pixels before direction is detected; default 10 | |
| 164 | | `type` | `"touch"`, `"pointer"`, or `"wheel"` (default: `"touch,pointer"`) | |
| 165 | |
| 166 | ## Text |
| 167 | |
| 168 | ### SplitText |
| 169 | |
| 170 | Splits an element’s text into characters, words, and/or lines (each in its own element) for staggered or per-unit animation. Use when animating text character-by-character, word-by-word, or line-by-line. Returns an instance with **chars**, **words**, **lines** (and **masks** when `mask` is set). Restore original markup with **revert()** or let **gsap.context()** revert. Integrates with **gsap.context()**, **matchMedia()**, and **useGSAP()**. API: **SplitText.create(target, vars)** (target = selector, element, or array). |
| 171 | |
| 172 | ```javascript |
| 173 | gsap.registerPlugin(SplitText); |
| 174 | |
| 175 | const split = SplitText.create(".heading", { type: "words, chars" }); |
| 176 | gsap.from(split.chars, { opacity: 0, y: 20, stagger: 0.03, duration: 0.4 }); |
| 177 | // later: split.revert() or let gsap.context() cleanup revert |
| 178 | ``` |
| 179 | |
| 180 | With **onSplit()** (v3.13.0+), animations run on each split and on re-split when **autoSplit** is used; returning a tween/timeline from **onSplit()** lets SplitText clean up and sync progress on re-split: |
| 181 | |
| 182 | ```javascript |
| 183 | SplitText.create(".split", { |
| 184 | type: "lines", |
| 185 | autoSplit: true, |
| 186 | onSplit(self) { |
| 187 | return gsap.from(self.lines, { y: 100, opacity: 0, stagger: 0.05, duration: 0.5 }); |
| 188 | } |
| 189 | }); |
| 190 | ``` |
| 191 | |
| 192 | **SplitText — key config (SplitText.create vars):** |
| 193 | |
| 194 | | Option | Description | |
| 195 | |--------|-------------| |
| 196 | | **type** | Comma-separated: `"chars"`, `"words"`, `"lines"`. Default `"chars,words,lines"`. Only split what is needed (e.g. `"words, chars"` if not using lines) for performance. Avoid chars-only without words/lines or use **smartWrap: true** to prevent odd line breaks. | |
| 197 | | **charsClass**, **wordsClass**, **linesClass** | CSS class on each split element. Append `"++"` to add an incremented class (e.g. `linesClass: "line++"` → `line1`, `line2`, …). | |
| 198 | | **aria** | `"auto"` (default), `"hidden"`, or `"none"`. Accessibility: `"auto"` adds `aria-label` on the split element and `aria-hidden` on line/word/char elements so screen readers read the label; `"hidden"` hides all from readers; `"none"` leaves aria unchanged. Use `"none"` plus a screen-reader-only duplicate if nested links/semantics must be exposed. | |
| 199 | | **autoSplit** | When `true`, reverts and re-splits when fonts finish loading or when the element width changes (and lines are split), avoiding wrong line breaks. **Animations must be created inside onSplit()** so they target the newly split elements; **return** the animation from **onSplit()** for automatic cleanup and time-sync on re-split. | |
| 200 | | **onSplit(self)** | Callback when split completes (and on each re-split if **autoSplit** is `true`). Receives the SplitText instance. Returning a GSAP tween or timeline enables automatic revert/sync of that animation when re-splitting. | |
| 201 | | **mask** | `"lines"`, `"words"`, or `"chars"`. Wraps each unit in an extra element with `overflow: clip` for mask/reveal effects. Only one type; access wrappers on the instance’s **masks** array (or use class `-mask` if a class is set). | |
| 202 | | **tag** | Wrapper element tag; default `"div"`. Use `"span"` for inline (note: transforms like rotation/scale may not render on inline elements in some browsers). | |
| 203 | | **deepSlice** | When `true` (default), nested elements (e.g. `<strong>`) that span multiple lines are subdivided so lines don’t stretch vertically. Only applies when splitting lines. | |
| 204 | | **ignore** | Selector or element(s) to leave unsplit (e.g. `ignore: "sup"`). | |
| 205 | | **smartWrap** | When splitting **chars** only, wraps words in a `white-space: nowrap` span to avoid mid-word line breaks. Ignored if words or lines are split. Default `false`. | |
| 206 | | **wordDelimiter** | Word boundary: string (default `" "`), RegExp, or `{ delimiter: RegExp, replaceWith: string }` for custom splitting (e.g. zero-width joiner for hashtags, or non-Latin). | |
| 207 | | **prepareText(text, parent)** | Function that receives raw text and parent element; return modified text before splitting (e.g. to insert break markers for languages without spaces). | |
| 208 | | **propIndex** | When `true`, adds a CSS variable with index on each split element (e.g. `--word: 1`, `--char: 2`). | |
| 209 | | **reduceWhiteSpace** | Collapse consecutive spaces; default `true`. From v3.13.0 also honors line breaks and can insert `<br>` for `<pre>`. | |
| 210 | | **onRevert** | Callback when the instance is reverted. | |
| 211 | |
| 212 | **Tips:** Split only what is animated (e.g. skip chars if only animating words). For custom fonts, split after they load (e.g. `document.fonts.ready.then(...)`) or use **autoSplit: true** with **onSplit()**. To avoid kerning shift when splitting chars, use CSS `font-kerning: none; text-rendering: optimizeSpeed;`. Avoid `text-wrap: balance`; it can interfere with splitting. SplitText does not support SVG `<text>`. |
| 213 | |
| 214 | **Learn more:** [SplitText](https://gsap.com/docs/v3/Plugins/SplitText/) |
| 215 | |
| 216 | ### ScrambleText |
| 217 | |
| 218 | Animates text with a scramble/glitch effect. Use when revealing or transitioning text with a scramble. |
| 219 | |
| 220 | ```javascript |
| 221 | gsap.registerPlugin(ScrambleTextPlugin); |
| 222 | |
| 223 | gsap.to(".text", { |
| 224 | duration: 1, |
| 225 | scrambleText: { text: "New message", chars: "01", revealDelay: 0.5 } |
| 226 | }); |
| 227 | ``` |
| 228 | |
| 229 | ## SVG |
| 230 | |
| 231 | ### DrawSVG (DrawSVGPlugin) |
| 232 | |
| 233 | Reveals or hides the stroke of SVG elements by animating `stroke-dashoffset` / `stroke-dasharray`. Works on `<path>`, `<line>`, `<polyline>`, `<polygon>`, `<rect>`, `<ellipse>`. Use when “drawing” or “erasing” strokes. |
| 234 | |
| 235 | **drawSVG value:** Describes the **visible segment** of the stroke along the path (start and end positions), not “animate from A to B over time.” Format: `"start end"` in percent or length. Examples: `"0% 100%"` = full stroke; `"20% 80%"` = stroke only between 20% and 80% (gaps at both ends). The tween animates from the element’s **current** segment to the **target** segment — e.g. `gsap.to("#path", { drawSVG: "0% 100%" })` goes from whatever it is now to full stroke. Single value (e.g. `0`, `"100%"`) means start is 0: `"100%"` is equivalent to `"0% 100%"`. |
| 236 | |
| 237 | **Required:** The element must have a visible stroke — set `stroke` and `stroke-width` in CSS or as SVG attributes; otherwise nothing is drawn. |
| 238 | |
| 239 | ```javascript |
| 240 | gsap.registerPlugin(DrawSVGPlugin); |
| 241 | |
| 242 | // draw from nothing to full stroke |
| 243 | gsap.from("#path", { duration: 1, drawSVG: 0 }); |
| 244 | // or explicit segment: from 0–0 to 0–100% |
| 245 | gsap.fromTo("#path", { drawSVG: "0% 0%" }, { drawSVG: "0% 100%", duration: 1 }); |
| 246 | // stroke only in the middle (gaps at ends) |
| 247 | gsap.to("#path", { duration: 1, drawSVG: "20% 80%" }); |
| 248 | ``` |
| 249 | |
| 250 | **Caveats:** Only affects stroke (not fill). Prefer single-segment `<path>` elements; multi-segment paths can render oddly in some browsers. Contents of `<use>` cannot be visually changed. **DrawSVGPlugin.getLength(element)** and **DrawSVGPlugin.getPosition(element)** return stroke length and current position. |
| 251 | |
| 252 | **Learn more:** [DrawSVG](https://gsap.com/docs/v3/Plugins/DrawSVGPlugin) |
| 253 | |
| 254 | ### MorphSVG (MorphSVGPlugin) |
| 255 | |
| 256 | Morphs one SVG shape into another by animating the `d` attribute (path data). Start and end shapes do not need the same number of points — MorphSVG converts to cubic beziers and adds points as needed. Use for icon-to-icon morphs, shape transitions, or path-based animations. Works on `<path>`, `<polyline>`, and `<polygon>`; `<circle>`, `<rect>`, `<ellipse>`, and `<line>` are converted internally or via **MorphSVGPlugin.convertToPath(selector | element)** (replaces the element in the DOM with a `<path>`). |
| 257 | |
| 258 | **morphSVG value:** Can be a **selector** (e.g. `"#lightning"`), an **element**, **raw path data** (e.g. `"M47.1,0.8 73.3,0.8..."`), or for polygon/polyline a **points string** (e.g. `"240,220 240,70 70,70 70,220"`). For full config use the **object form** with **shape** as the only required property. |
| 259 | |
| 260 | ```javascript |
| 261 | gsap.registerPlugin(MorphSVGPlugin); |
| 262 | |
| 263 | // convert primitives to path first if needed: |
| 264 | MorphSVGPlugin.convertToPath("circle, rect, ellipse, line"); |
| 265 | |
| 266 | gsap.to("#diamond", { duration: 1, morphSVG: "#lightning", ease: "power2.inOut" }); |
| 267 | // object form: |
| 268 | gsap.to("#diamond", { |
| 269 | duration: 1, |
| 270 | morphSVG: { shape: "#lightning", type: "rotational", shapeIndex: 2 } |
| 271 | }); |
| 272 | |
| 273 | ``` |
| 274 | |
| 275 | **MorphSVG — key config (morphSVG object):** |
| 276 | |
| 277 | | Option | Description | |
| 278 | |--------|-------------| |
| 279 | | **shape** | _(Required.)_ Target shape: selector, element, or raw path string. | |
| 280 | | **type** | `"linear"` (default) or `"rotational"`. Rotational uses angle/length interpolation and can avoid kinks mid-morph; try it when linear looks wrong. | |
| 281 | | **map** | How segments are matched: `"size"` (default), `"position"`, or `"complexity"`. Use when start/end segments don’t line up; if none work, split into multiple paths and morph each. | |
| 282 | | **shapeIndex** | Offsets which point in the start path maps to the first point in the end path (avoids shape “crossing over” or inverting). Number for single-segment paths; **array** for multi-segment (e.g. `[5, 1, -8]`). Negative reverses that segment. Use **shapeIndex: "log"** once to log the auto-calculated value, then paste the number/array into the tween. **findShapeIndex(start, end)** (separate utility) provides an interactive UI to find a good value. Only applies to closed paths. | |
| 283 | | **smooth** | (v3.14+). Adds smoothing points. Number (e.g. `80`), `"auto"`, or object: `{ points: 40 \| "auto", redraw: true \| false, persist: true \| false }`. `redraw: false` keeps original anchors (perfect fidelity, less even spacing). `persist: false` removes added points when the tween ends. Use when the default morph looks jagged or unnatural. | |
| 284 | | **curveMode** | Boolean (v3.14+). Interpolates control-handle angle/length instead of raw x/y to avoid kinks on curves. Try if a morph has a mid-morph kink. | |
| 285 | | **origin** | Rotation origin for **type: "rotational"**. String: `"50% 50%"` (default) or `"20% 60%, 35% 90%"` for different start/end origins. | |
| 286 | | **precision** | Decimal places for output path data; default `2`. | |
| 287 | | **precompile** | Array of precomputed path strings (or use **precompile: "log"** once, copy from console). Skips expensive startup calculations; use for very complex morphs. Only for `<path>` (convert polygon/polyline first). | |
| 288 | | **render** | Function(rawPath, target) called each update — e.g. draw to canvas. RawPath is an array of segments (each segment = array of alternating x,y cubic bezier coords). | |
| 289 | | **updateTarget** | When using **render** (e.g. canvas-only), set **updateTarget: false** so the original `<path>` is not updated. **MorphSVGPlugin.defaultUpdateTarget** sets default. | |
| 290 | |
| 291 | **Utilities:** **MorphSVGPlugin.convertToPath(selector | element)** converts circle/rect/ellipse/line/polygon/polyline to `<path>` in the DOM. **MorphSVGPlugin.rawPathToString(rawPath)** and **stringToRawPath(d)** convert between path strings and raw arrays. The plugin stores the original `d` on the target (e.g. for tweening back: `morphSVG: "#originalId"` or the same element). |
| 292 | |
| 293 | **Tips:** For twisted or inverted morphs, set **shapeIndex** (use `"log"` or findShapeIndex()). For multi-segment paths, **shapeIndex** is an array (one value per segment). Precompile only when the first frame is slow; it does not fix jank during the tween (simplify the SVG or reduce size if needed). |
| 294 | |
| 295 | **Learn more:** [MorphSVG](https://gsap.com/docs/v3/Plugins/MorphSVGPlugin) |
| 296 | |
| 297 | ### MotionPath (MotionPathPlugin) |
| 298 | |
| 299 | Animates an element along an SVG path. Use when moving an object along a path (e.g. a curve or custom route). |
| 300 | |
| 301 | ```javascript |
| 302 | gsap.registerPlugin(MotionPathPlugin); |
| 303 | |
| 304 | gsap.to(".dot", { |
| 305 | duration: 2, |
| 306 | motionPath: { path: "#path", align: "#path", alignOrigin: [0.5, 0.5] } |
| 307 | }); |
| 308 | ``` |
| 309 | |
| 310 | **MotionPath — key config (motionPath object):** |
| 311 | |
| 312 | | Option | Description | |
| 313 | |--------|-------------| |
| 314 | | `path` | SVG path element, selector, or path data string | |
| 315 | | `align` | Path element or selector to align the target to | |
| 316 | | `alignOrigin` | `[x, y]` origin (0–1); default `[0.5, 0.5]` | |
| 317 | | `autoRotate` | Rotate element to follow path tangent | |
| 318 | | `curviness` | 0–2; path smoothing | |
| 319 | |
| 320 | ### MotionPathHelper |
| 321 | |
| 322 | Visual editor for MotionPath (alignment, offset). Use during development to tune path alignment. |
| 323 | |
| 324 | ```javascript |
| 325 | gsap.registerPlugin(MotionPathPlugin, MotionPathHelperPlugin); |
| 326 | |
| 327 | const helper = MotionPathHelper.create(".dot", "#path", { end: 0.5 }); |
| 328 | // adjust in UI, then use helper.path or helper.getProgress() in your animation |
| 329 | ``` |
| 330 | |
| 331 | ## Easing |
| 332 | |
| 333 | ### CustomEase |
| 334 | |
| 335 | Custom easing curves (cubic-bezier or SVG path). Use when a built-in ease is not enough. Basic usage is covered in gsap-core; register when using: |
| 336 | |
| 337 | ```javascript |
| 338 | gsap.registerPlugin(CustomEase); |
| 339 | const ease = CustomEase.create("name", ".17,.67,.83,.67"); |
| 340 | gsap.to(".el", { x: 100, ease: ease, duration: 1 }); |
| 341 | ``` |
| 342 | |
| 343 | ### EasePack |
| 344 | |
| 345 | Adds more named eases (e.g. SlowMo, RoughEase, ExpoScaleEase). Register and use the ease names in tweens. |
| 346 | |
| 347 | ### CustomWiggle |
| 348 | |
| 349 | Wiggle/shake easing. Use when a value should “wiggle” (multiple oscillations). |
| 350 | |
| 351 | ### CustomBounce |
| 352 | |
| 353 | Bounce-style easing with configurable strength. |
| 354 | |
| 355 | ## Physics |
| 356 | |
| 357 | ### Physics2D (Physics2DPlugin) |
| 358 | |
| 359 | 2D physics (velocity, angle, gravity). Use when animating with simple physics (e.g. projectiles, bouncing). |
| 360 | |
| 361 | ```javascript |
| 362 | gsap.registerPlugin(Physics2DPlugin); |
| 363 | |
| 364 | gsap.to(".ball", { |
| 365 | duration: 2, |
| 366 | physics2D: { |
| 367 | velocity: 250, |
| 368 | angle: 80, |
| 369 | gravity: 500 |
| 370 | } |
| 371 | }); |
| 372 | ``` |
| 373 | |
| 374 | ### PhysicsProps ( |