[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6M34GDSQJAMT3J7N473MAFM":3,"skill-same:01M6M34GDSQJAMT3J7N473MAFM":73},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":53,"commitSha":54,"skillDirectory":55,"forksCount":13,"repositoryHtmlUrl":56,"repositoryHomepageUrl":6,"ownerHtmlUrl":57,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":58,"install":59,"resources":72},"01M6M34GDSQJAMT3J7N473MAFM","gsap-utils",null,"Official GSAP skill for gsap.utils — clamp, mapRange, normalize, interpolate, random, snap, toArray, wrap, pipe. Use when the user asks about gsap.utils, clamp, mapRange, random, snap, toArray, wrap, or helper utilities in GSAP.","endman100\u002Fskill-router-nexus","endman100","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F31997019?v=4","01M6KPDX17BYDWW4RRB0TNGGMX","01M6KPDX64Y2QBEWVFG5W5PWPF",0,"MIT","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FWeb-Design\u002Ffrontend-and-motion-implementation\u002Fopen-design-gsap-utils\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"gsap","gsap utils","utils","normalize","when","value","for","snap","random","about","Utilities","helper","github","pipe","wrap","motion","use","Animation","https","official","prototype","2026-11-10 10:12:30",false,"---\nname: gsap-utils\ndescription: |\n  Official GSAP skill for gsap.utils — clamp, mapRange, normalize, interpolate, random, snap, toArray, wrap, pipe. Use when the user asks about gsap.utils, clamp, mapRange, random, snap, toArray, wrap, or helper utilities in GSAP.\ntriggers:\n  - \"gsap utils\"\n  - \"clamp animation value\"\n  - \"maprange\"\n  - \"snap animation\"\n  - \"gsap random\"\nlicense: MIT\nod:\n  mode: prototype\n  category: animation-motion\n  upstream: \"https:\u002F\u002Fgithub.com\u002Fgreensock\u002Fgsap-skills\"\n---\n\n# gsap.utils\n\n> Curated from GreenSock's official GSAP skills: https:\u002F\u002Fgithub.com\u002Fgreensock\u002Fgsap-skills\n\n## When to Use This Skill\n\nApply when writing or reviewing code that uses **gsap.utils** for math, array\u002Fcollection handling, unit parsing, or value mapping in animations (e.g. mapping scroll to a value, randomizing, snapping to a grid, or normalizing inputs).\n\n**Related skills:** Use with **gsap-core**, **gsap-timeline**, and **gsap-scrolltrigger** when building animations; CustomEase and other easing utilities are in **gsap-plugins**.\n\n## Overview\n\n**gsap.utils** provides pure helpers; no need to register. Use in tween vars (e.g. function-based values), in ScrollTrigger or Observer callbacks, or in any JS that drives GSAP. All are on **gsap.utils** (e.g. `gsap.utils.clamp()`).\n\n**Omitting the value: function form.** Many utils accept the value to transform as the **last** argument. If you omit that argument, the util returns a **function** that accepts the value later. Use the function form when you need to clamp, map, normalize, or snap many values with the same config (e.g. in a mousemove handler or tween callback). **Exception: random()** — pass **true** as the last argument to get a reusable function (do not omit the value); see [random()](https:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FGSAP\u002FUtilityMethods\u002Frandom()).\n\n```javascript\n\u002F\u002F With value: returns the result\ngsap.utils.clamp(0, 100, 150); \u002F\u002F 100\n\n\u002F\u002F Without value: returns a function you call with the value later\nlet c = gsap.utils.clamp(0, 100);\nc(150);  \u002F\u002F 100\nc(-10);  \u002F\u002F 0\n```\n\n## Clamping and Ranges\n\n### clamp(min, max, value?)\n\nConstrains a value between min and max. Omit **value** to get a function: `clamp(min, max)(value)`.\n\n```javascript\ngsap.utils.clamp(0, 100, 150); \u002F\u002F 100\ngsap.utils.clamp(0, 100, -10); \u002F\u002F 0\n\nlet clampFn = gsap.utils.clamp(0, 100);\nclampFn(150); \u002F\u002F 100\n```\n\n### mapRange(inMin, inMax, outMin, outMax, value?)\n\nMaps a value from one range to another. Use when converting scroll position, progress (0–1), or input range to an animation range. Omit **value** to get a function: `mapRange(inMin, inMax, outMin, outMax)(value)`.\n\n```javascript\ngsap.utils.mapRange(0, 100, 0, 500, 50);  \u002F\u002F 250\ngsap.utils.mapRange(0, 1, 0, 360, 0.5);   \u002F\u002F 180 (progress to degrees)\n\nlet mapFn = gsap.utils.mapRange(0, 100, 0, 500);\nmapFn(50);  \u002F\u002F 250\n```\n\n### normalize(min, max, value?)\n\nReturns a value normalized to 0–1 for the given range. Inverse of mapping when the target range is 0–1. Omit **value** to get a function: `normalize(min, max)(value)`.\n\n```javascript\ngsap.utils.normalize(0, 100, 50);   \u002F\u002F 0.5\ngsap.utils.normalize(100, 300, 200); \u002F\u002F 0.5\n\nlet normFn = gsap.utils.normalize(0, 100);\nnormFn(50); \u002F\u002F 0.5\n```\n\n### interpolate(start, end, progress?)\n\nInterpolates between two values at a given progress (0–1). Handles numbers, colors, and objects with matching keys. Omit **progress** to get a function: `interpolate(start, end)(progress)`.\n\n```javascript\ngsap.utils.interpolate(0, 100, 0.5);       \u002F\u002F 50\ngsap.utils.interpolate(\"#ff0000\", \"#0000ff\", 0.5); \u002F\u002F mid color\ngsap.utils.interpolate({ x: 0, y: 0 }, { x: 100, y: 50 }, 0.5); \u002F\u002F { x: 50, y: 25 }\n\nlet lerp = gsap.utils.interpolate(0, 100);\nlerp(0.5); \u002F\u002F 50\n```\n\n## Random and Snap\n\n### random(minimum, maximum[, snapIncrement, returnFunction]) \u002F random(array[, returnFunction])\n\nReturns a random number in the range **minimum**–**maximum**, or a random element from an **array**. Optional **snapIncrement** snaps the result to the nearest multiple (e.g. `5` → multiples of 5). **To get a reusable function**, pass **true** as the last argument (**returnFunction**); the returned function takes no args and returns a new random value each time. This is the only util that uses `true` for the function form instead of omitting the value.\n\n```javascript\n\u002F\u002F immediate value: number in range\ngsap.utils.random(-100, 100);        \u002F\u002F e.g. 42.7\ngsap.utils.random(0, 500, 5);        \u002F\u002F 0–500, snapped to nearest 5\n\n\u002F\u002F reusable function: pass true as last argument\nlet randomFn = gsap.utils.random(-200, 500, 10, true);\nrandomFn();  \u002F\u002F random value in range, snapped to 10\nrandomFn();  \u002F\u002F another random value\n\n\u002F\u002F array: pick one value at random\ngsap.utils.random([\"red\", \"blue\", \"green\"]);  \u002F\u002F \"red\", \"blue\", or \"green\"\nlet randomFromArray = gsap.utils.random([0, 100, 200], true);\nrandomFromArray();  \u002F\u002F 0, 100, or 200\n```\n\n**String form in tween vars:** use `\"random(-100, 100)\"`, `\"random(-100, 100, 5)\"`, or `\"random([0, 100, 200])\"`; GSAP evaluates it per target.\n\n```javascript\ngsap.to(\".box\", { x: \"random(-100, 100, 5)\", duration: 1 });\ngsap.to(\".item\", { backgroundColor: \"random([red, blue, green])\" });\n```\n\n### snap(snapTo, value?)\n\nSnaps a value to the nearest multiple of **snapTo**, or to the nearest value in an array of allowed values. Omit **value** to get a function: `snap(snapTo)(value)` (or `snap(snapArray)(value)`).\n\n```javascript\ngsap.utils.snap(10, 23);     \u002F\u002F 20\ngsap.utils.snap(0.25, 0.7);  \u002F\u002F 0.75\ngsap.utils.snap([0, 100, 200], 150); \u002F\u002F 100 or 200 (nearest in array)\n\nlet snapFn = gsap.utils.snap(10);\nsnapFn(23); \u002F\u002F 20\n```\n\nUse in tweens for grid or step-based animation:\n\n```javascript\ngsap.to(\".x\", { x: 200, snap: { x: 20 } });\n```\n\n### shuffle(array)\n\nReturns a new array with the same elements in random order. Use for randomizing order (e.g. stagger from \"random\" with a copy).\n\n```javascript\ngsap.utils.shuffle([1, 2, 3, 4]); \u002F\u002F e.g. [3, 1, 4, 2]\n```\n\n### distribute(config)\n\n**Returns a function** that assigns a value to each target based on its position in the array (or in a grid). Used internally for advanced staggers; use it whenever you need values spread across many elements (e.g. scale, opacity, x, delay). The returned function receives `(index, target, targets)` — either call it manually or pass the result directly into a tween; GSAP will call it per target with index, element, and array.\n\n**Config (all optional):**\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `base` | Number | Starting value. Default `0`. |\n| `amount` | Number | Total to distribute across all targets (added to base). E.g. `amount: 1` with 100 targets → 0.01 between each. Use **each** instead to set a fixed step per target. |\n| `each` | Number | Amount to add between each target (added to base). E.g. `each: 1` with 4 targets → 0, 1, 2, 3. Use **amount** instead to split a total. |\n| `from` | Number \\| String \\| Array | Where distribution starts: index, or `\"start\"`, `\"center\"`, `\"edges\"`, `\"random\"`, `\"end\"`, or ratios like `[0.25, 0.75]`. Default `0`. |\n| `grid` | String \\| Array | Use grid position instead of flat index: `[rows, columns]` (e.g. `[5, 10]`) or `\"auto\"` to detect. Omit for flat array. |\n| `axis` | String | For grid: limit to one axis (`\"x\"` or `\"y\"`). |\n| `ease` | Ease | Distribute values along an ease curve (e.g. `\"power1.inOut\"`). Default `\"none\"`. |\n\n**In a tween:** pass the result of `distribute(config)` as the property value; GSAP calls the function for each target with `(index, target, targets)`.\n\n```javascript\n\u002F\u002F Scale: middle elements 0.5, outer edges 3 (amount 2.5 distributed from center)\ngsap.to(\".class\", {\n  scale: gsap.utils.distribute({\n    base: 0.5,\n    amount: 2.5,\n    from: \"center\"\n  })\n});\n```\n\n**Manual use:** call the returned function with `(index, target, targets)` to get the value for that index.\n\n```javascript\nconst distributor = gsap.utils.distribute({\n  base: 50,\n  amount: 100,\n  from: \"center\",\n  ease: \"power1.inOut\"\n});\nconst targets = gsap.utils.toArray(\".box\");\nconst valueForIndex2 = distributor(2, targets[2], targets);\n```\n\nSee [distribute()](https:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FGSAP\u002FUtilityMethods\u002Fdistribute\u002F) for more.\n\n## Units and Parsing\n\n### getUnit(value)\n\nReturns the unit string of a value (e.g. `\"px\"`, `\"%\"`, `\"deg\"`). Use when normalizing or converting values.\n\n```javascript\ngsap.utils.getUnit(\"100px\");   \u002F\u002F \"px\"\ngsap.utils.getUnit(\"50%\");     \u002F\u002F \"%\"\ngsap.utils.getUnit(42);        \u002F\u002F \"\" (unitless)\n```\n\n### unitize(value, unit)\n\nAppends a unit to a number, or returns the value as-is if it already has a unit. Use when building CSS values or tween end values.\n\n```javascript\ngsap.utils.unitize(100, \"px\");  \u002F\u002F \"100px\"\ngsap.utils.unitize(\"2rem\", \"px\"); \u002F\u002F \"2rem\" (unchanged)\n```\n\n### splitColor(color, returnHSL?)\n\nConverts a color string into an array: **[red, green, blue]** (0–255), or **[red, green, blue, alpha]** (4 elements for RGBA when alpha is present or required). Pass **true** as the second argument (**returnHSL**) to get **[hue, saturation, lightness]** or **[hue, saturation, lightness, alpha]** (HSL\u002FHSLA) instead. Works with `\"rgb()\"`, `\"rgba()\"`, `\"hsl()\"`, `\"hsla()\"`, hex, and named colors (e.g. `\"red\"`). Use when animating color components or building gradients. See [splitColor()](https:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FGSAP\u002FUtilityMethods\u002FsplitColor\u002F).\n\n```javascript\ngsap.utils.splitColor(\"red\");                    \u002F\u002F [255, 0, 0]\ngsap.utils.splitColor(\"#6fb936\");                \u002F\u002F [111, 185, 54]\ngsap.utils.splitColor(\"rgba(204, 153, 51, 0.5)\"); \u002F\u002F [204, 153, 51, 0.5] (4 elements)\ngsap.utils.splitColor(\"#6fb936\", true);          \u002F\u002F [94, 55, 47] (HSL: hue, saturation, lightness)\n```\n\n## Arrays and Collections\n\n### selector(scope)\n\nReturns a scoped selector function that finds elements only within the given element (or ref). Use in components so selectors like `\".box\"` match only descendants of that component, not the whole document. Accepts a DOM element or a ref (e.g. React ref; handles `.current`).\n\n```javascript\nconst q = gsap.utils.selector(containerRef);\nq(\".box\");        \u002F\u002F array of .box elements inside container\ngsap.to(q(\".circle\"), { x: 100 });\n```\n\n### toArray(value, scope?)\n\nConverts a value to an array: selector string (scoped to element), NodeList, HTMLCollection, single element, or array. Use when passing mixed inputs to GSAP (e.g. targets) and a true array is needed.\n\n```javascript\ngsap.utils.toArray(\".item\");           \u002F\u002F array of elements\ngsap.utils.toArray(\".item\", container); \u002F\u002F scoped to container\ngsap.utils.toArray(nodeList);          \u002F\u002F [ ... ] from NodeList\n```\n\n### pipe(...functions)\n\nComposes functions: **pipe(f1, f2, f3)(value)** returns f3(f2(f1(value))). Use when applying a chain of transforms (e.g. normalize → mapRange → snap) in a tween or callback.\n\n```javascript\nconst fn = gsap.utils.pipe(\n  (v) => gsap.utils.normalize(0, 100, v),\n  (v) => gsap.utils.snap(0.1, v)\n);\nfn(50); \u002F\u002F normalized then snapped\n```\n\n### wrap(min, max, value?)\n\nWraps a value into the range min–max (inclusive min, exclusive max). Use for infinite scroll or cyclic values. Omit **value** to get a function: `wrap(min, max)(value)`.\n\n```javascript\ngsap.utils.wrap(0, 360, 370);  \u002F\u002F 10\ngsap.utils.wrap(0, 360, -10);   \u002F\u002F 350\n\nlet wrapFn = gsap.utils.wrap(0, 360);\nwrapFn(370); \u002F\u002F 10\n```\n\n### wrapYoyo(min, max, value?)\n\nWraps value in range with a yoyo (bounces at ends). Use for back-and-forth within a range. Omit **value** to get a function: `wrapYoyo(min, max)(value)`.\n\n```javascript\ngsap.utils.wrapYoyo(0, 100, 150); \u002F\u002F 50 (bounces back)\n\nlet wrapY = gsap.utils.wrapYoyo(0, 100);\nwrapY(150); \u002F\u002F 50\n```\n\n## Best practices\n\n- ✅ Omit the value argument to get a reusable function when the same range\u002Fconfig is used many times (e.g. scroll handler, tween callback): `let mapFn = gsap.utils.mapRange(0, 1, 0, 360); mapFn(progress)`.\n- ✅ Use **snap** for grid-aligned or step-based values; use **toArray** when GSAP or your code needs a real array from a selector or NodeList.\n- ✅ Use **gsap.utils.selector(scope)** in components so selectors are scoped to a container or ref.\n\n## Do Not\n\n- ❌ Assume **mapRange** \u002F **normalize** handle units; they work on numbers. Use **getUnit** \u002F **unitize** when units matter.\n- ❌ Override or rely on undocumented behavior; stick to the documented API.\n\n### Learn More\n\nhttps:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FHelperFunctions\n","# gsap.utils\n\n> Curated from GreenSock's official GSAP skills: https:\u002F\u002Fgithub.com\u002Fgreensock\u002Fgsap-skills\n\n## When to Use This Skill\n\nApply when writing or reviewing code that uses **gsap.utils** for math, array\u002Fcollection handling, unit parsing, or value mapping in animations (e.g. mapping scroll to a value, randomizing, snapping to a grid, or normalizing inputs).\n\n**Related skills:** Use with **gsap-core**, **gsap-timeline**, and **gsap-scrolltrigger** when building animations; CustomEase and other easing utilities are in **gsap-plugins**.\n\n## Overview\n\n**gsap.utils** provides pure helpers; no need to register. Use in tween vars (e.g. function-based values), in ScrollTrigger or Observer callbacks, or in any JS that drives GSAP. All are on **gsap.utils** (e.g. `gsap.utils.clamp()`).\n\n**Omitting the value: function form.** Many utils accept the value to transform as the **last** argument. If you omit that argument, the util returns a **function** that accepts the value later. Use the function form when you need to clamp, map, normalize, or snap many values with the same config (e.g. in a mousemove handler or tween callback). **Exception: random()** — pass **true** as the last argument to get a reusable function (do not omit the value); see [random()](https:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FGSAP\u002FUtilityMethods\u002Frandom()).\n\n```javascript\n\u002F\u002F With value: returns the result\ngsap.utils.clamp(0, 100, 150); \u002F\u002F 100\n\n\u002F\u002F Without value: returns a function you call with the value later\nlet c = gsap.utils.clamp(0, 100);\nc(150);  \u002F\u002F 100\nc(-10);  \u002F\u002F 0\n```\n\n## Clamping and Ranges\n\n### clamp(min, max, value?)\n\nConstrains a value between min and max. Omit **value** to get a function: `clamp(min, max)(value)`.\n\n```javascript\ngsap.utils.clamp(0, 100, 150); \u002F\u002F 100\ngsap.utils.clamp(0, 100, -10); \u002F\u002F 0\n\nlet clampFn = gsap.utils.clamp(0, 100);\nclampFn(150); \u002F\u002F 100\n```\n\n### mapRange(inMin, inMax, outMin, outMax, value?)\n\nMaps a value from one range to another. Use when converting scroll position, progress (0–1), or input range to an animation range. Omit **value** to get a function: `mapRange(inMin, inMax, outMin, outMax)(value)`.\n\n```javascript\ngsap.utils.mapRange(0, 100, 0, 500, 50);  \u002F\u002F 250\ngsap.utils.mapRange(0, 1, 0, 360, 0.5);   \u002F\u002F 180 (progress to degrees)\n\nlet mapFn = gsap.utils.mapRange(0, 100, 0, 500);\nmapFn(50);  \u002F\u002F 250\n```\n\n### normalize(min, max, value?)\n\nReturns a value normalized to 0–1 for the given range. Inverse of mapping when the target range is 0–1. Omit **value** to get a function: `normalize(min, max)(value)`.\n\n```javascript\ngsap.utils.normalize(0, 100, 50);   \u002F\u002F 0.5\ngsap.utils.normalize(100, 300, 200); \u002F\u002F 0.5\n\nlet normFn = gsap.utils.normalize(0, 100);\nnormFn(50); \u002F\u002F 0.5\n```\n\n### interpolate(start, end, progress?)\n\nInterpolates between two values at a given progress (0–1). Handles numbers, colors, and objects with matching keys. Omit **progress** to get a function: `interpolate(start, end)(progress)`.\n\n```javascript\ngsap.utils.interpolate(0, 100, 0.5);       \u002F\u002F 50\ngsap.utils.interpolate(\"#ff0000\", \"#0000ff\", 0.5); \u002F\u002F mid color\ngsap.utils.interpolate({ x: 0, y: 0 }, { x: 100, y: 50 }, 0.5); \u002F\u002F { x: 50, y: 25 }\n\nlet lerp = gsap.utils.interpolate(0, 100);\nlerp(0.5); \u002F\u002F 50\n```\n\n## Random and Snap\n\n### random(minimum, maximum[, snapIncrement, returnFunction]) \u002F random(array[, returnFunction])\n\nReturns a random number in the range **minimum**–**maximum**, or a random element from an **array**. Optional **snapIncrement** snaps the result to the nearest multiple (e.g. `5` → multiples of 5). **To get a reusable function**, pass **true** as the last argument (**returnFunction**); the returned function takes no args and returns a new random value each time. This is the only util that uses `true` for the function form instead of omitting the value.\n\n```javascript\n\u002F\u002F immediate value: number in range\ngsap.utils.random(-100, 100);        \u002F\u002F e.g. 42.7\ngsap.utils.random(0, 500, 5);        \u002F\u002F 0–500, snapped to nearest 5\n\n\u002F\u002F reusable function: pass true as last argument\nlet randomFn = gsap.utils.random(-200, 500, 10, true);\nrandomFn();  \u002F\u002F random value in range, snapped to 10\nrandomFn();  \u002F\u002F another random value\n\n\u002F\u002F array: pick one value at random\ngsap.utils.random([\"red\", \"blue\", \"green\"]);  \u002F\u002F \"red\", \"blue\", or \"green\"\nlet randomFromArray = gsap.utils.random([0, 100, 200], true);\nrandomFromArray();  \u002F\u002F 0, 100, or 200\n```\n\n**String form in tween vars:** use `\"random(-100, 100)\"`, `\"random(-100, 100, 5)\"`, or `\"random([0, 100, 200])\"`; GSAP evaluates it per target.\n\n```javascript\ngsap.to(\".box\", { x: \"random(-100, 100, 5)\", duration: 1 });\ngsap.to(\".item\", { backgroundColor: \"random([red, blue, green])\" });\n```\n\n### snap(snapTo, value?)\n\nSnaps a value to the nearest multiple of **snapTo**, or to the nearest value in an array of allowed values. Omit **value** to get a function: `snap(snapTo)(value)` (or `snap(snapArray)(value)`).\n\n```javascript\ngsap.utils.snap(10, 23);     \u002F\u002F 20\ngsap.utils.snap(0.25, 0.7);  \u002F\u002F 0.75\ngsap.utils.snap([0, 100, 200], 150); \u002F\u002F 100 or 200 (nearest in array)\n\nlet snapFn = gsap.utils.snap(10);\nsnapFn(23); \u002F\u002F 20\n```\n\nUse in tweens for grid or step-based animation:\n\n```javascript\ngsap.to(\".x\", { x: 200, snap: { x: 20 } });\n```\n\n### shuffle(array)\n\nReturns a new array with the same elements in random order. Use for randomizing order (e.g. stagger from \"random\" with a copy).\n\n```javascript\ngsap.utils.shuffle([1, 2, 3, 4]); \u002F\u002F e.g. [3, 1, 4, 2]\n```\n\n### distribute(config)\n\n**Returns a function** that assigns a value to each target based on its position in the array (or in a grid). Used internally for advanced staggers; use it whenever you need values spread across many elements (e.g. scale, opacity, x, delay). The returned function receives `(index, target, targets)` — either call it manually or pass the result directly into a tween; GSAP will call it per target with index, element, and array.\n\n**Config (all optional):**\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `base` | Number | Starting value. Default `0`. |\n| `amount` | Number | Total to distribute across all targets (added to base). E.g. `amount: 1` with 100 targets → 0.01 between each. Use **each** instead to set a fixed step per target. |\n| `each` | Number | Amount to add between each target (added to base). E.g. `each: 1` with 4 targets → 0, 1, 2, 3. Use **amount** instead to split a total. |\n| `from` | Number \\| String \\| Array | Where distribution starts: index, or `\"start\"`, `\"center\"`, `\"edges\"`, `\"random\"`, `\"end\"`, or ratios like `[0.25, 0.75]`. Default `0`. |\n| `grid` | String \\| Array | Use grid position instead of flat index: `[rows, columns]` (e.g. `[5, 10]`) or `\"auto\"` to detect. Omit for flat array. |\n| `axis` | String | For grid: limit to one axis (`\"x\"` or `\"y\"`). |\n| `ease` | Ease | Distribute values along an ease curve (e.g. `\"power1.inOut\"`). Default `\"none\"`. |\n\n**In a tween:** pass the result of `distribute(config)` as the property value; GSAP calls the function for each target with `(index, target, targets)`.\n\n```javascript\n\u002F\u002F Scale: middle elements 0.5, outer edges 3 (amount 2.5 distributed from center)\ngsap.to(\".class\", {\n  scale: gsap.utils.distribute({\n    base: 0.5,\n    amount: 2.5,\n    from: \"center\"\n  })\n});\n```\n\n**Manual use:** call the returned function with `(index, target, targets)` to get the value for that index.\n\n```javascript\nconst distributor = gsap.utils.distribute({\n  base: 50,\n  amount: 100,\n  from: \"center\",\n  ease: \"power1.inOut\"\n});\nconst targets = gsap.utils.toArray(\".box\");\nconst valueForIndex2 = distributor(2, targets[2], targets);\n```\n\nSee [distribute()](https:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FGSAP\u002FUtilityMethods\u002Fdistribute\u002F) for more.\n\n## Units and Parsing\n\n### getUnit(value)\n\nReturns the unit string of a value (e.g. `\"px\"`, `\"%\"`, `\"deg\"`). Use when normalizing or converting values.\n\n```javascript\ngsap.utils.getUnit(\"100px\");   \u002F\u002F \"px\"\ngsap.utils.getUnit(\"50%\");     \u002F\u002F \"%\"\ngsap.utils.getUnit(42);        \u002F\u002F \"\" (unitless)\n```\n\n### unitize(value, unit)\n\nAppends a unit to a number, or returns the value as-is if it already has a unit. Use when building CSS values or tween end values.\n\n```javascript\ngsap.utils.unitize(100, \"px\");  \u002F\u002F \"100px\"\ngsap.utils.unitize(\"2rem\", \"px\"); \u002F\u002F \"2rem\" (unchanged)\n```\n\n### splitColor(color, returnHSL?)\n\nConverts a color string into an array: **[red, green, blue]** (0–255), or **[red, green, blue, alpha]** (4 elements for RGBA when alpha is present or required). Pass **true** as the second argument (**returnHSL**) to get **[hue, saturation, lightness]** or **[hue, saturation, lightness, alpha]** (HSL\u002FHSLA) instead. Works with `\"rgb()\"`, `\"rgba()\"`, `\"hsl()\"`, `\"hsla()\"`, hex, and named colors (e.g. `\"red\"`). Use when animating color components or building gradients. See [splitColor()](https:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FGSAP\u002FUtilityMethods\u002FsplitColor\u002F).\n\n```javascript\ngsap.utils.splitColor(\"red\");                    \u002F\u002F [255, 0, 0]\ngsap.utils.splitColor(\"#6fb936\");                \u002F\u002F [111, 185, 54]\ngsap.utils.splitColor(\"rgba(204, 153, 51, 0.5)\"); \u002F\u002F [204, 153, 51, 0.5] (4 elements)\ngsap.utils.splitColor(\"#6fb936\", true);          \u002F\u002F [94, 55, 47] (HSL: hue, saturation, lightness)\n```\n\n## Arrays and Collections\n\n### selector(scope)\n\nReturns a scoped selector function that finds elements only within the given element (or ref). Use in components so selectors like `\".box\"` match only descendants of that component, not the whole document. Accepts a DOM element or a ref (e.g. React ref; handles `.current`).\n\n```javascript\nconst q = gsap.utils.selector(containerRef);\nq(\".box\");        \u002F\u002F array of .box elements inside container\ngsap.to(q(\".circle\"), { x: 100 });\n```\n\n### toArray(value, scope?)\n\nConverts a value to an array: selector string (scoped to element), NodeList, HTMLCollection, single element, or array. Use when passing mixed inputs to GSAP (e.g. targets) and a true array is needed.\n\n```javascript\ngsap.utils.toArray(\".item\");           \u002F\u002F array of elements\ngsap.utils.toArray(\".item\", container); \u002F\u002F scoped to container\ngsap.utils.toArray(nodeList);          \u002F\u002F [ ... ] from NodeList\n```\n\n### pipe(...functions)\n\nComposes functions: **pipe(f1, f2, f3)(value)** returns f3(f2(f1(value))). Use when applying a chain of transforms (e.g. normalize → mapRange → snap) in a tween or callback.\n\n```javascript\nconst fn = gsap.utils.pipe(\n  (v) => gsap.utils.normalize(0, 100, v),\n  (v) => gsap.utils.snap(0.1, v)\n);\nfn(50); \u002F\u002F normalized then snapped\n```\n\n### wrap(min, max, value?)\n\nWraps a value into the range min–max (inclusive min, exclusive max). Use for infinite scroll or cyclic values. Omit **value** to get a function: `wrap(min, max)(value)`.\n\n```javascript\ngsap.utils.wrap(0, 360, 370);  \u002F\u002F 10\ngsap.utils.wrap(0, 360, -10);   \u002F\u002F 350\n\nlet wrapFn = gsap.utils.wrap(0, 360);\nwrapFn(370); \u002F\u002F 10\n```\n\n### wrapYoyo(min, max, value?)\n\nWraps value in range with a yoyo (bounces at ends). Use for back-and-forth within a range. Omit **value** to get a function: `wrapYoyo(min, max)(value)`.\n\n```javascript\ngsap.utils.wrapYoyo(0, 100, 150); \u002F\u002F 50 (bounces back)\n\nlet wrapY = gsap.utils.wrapYoyo(0, 100);\nwrapY(150); \u002F\u002F 50\n```\n\n## Best practices\n\n- ✅ Omit the value argument to get a reusable function when the same range\u002Fconfig is used many times (e.g. scroll handler, tween callback): `let mapFn = gsap.utils.mapRange(0, 1, 0, 360); mapFn(progress)`.\n- ✅ Use **snap** for grid-aligned or step-based values; use **toArray** when GSAP or your code needs a real array from a selector or NodeList.\n- ✅ Use **gsap.utils.selector(scope)** in components so selectors are scoped to a container or ref.\n\n## Do Not\n\n- ❌ Assume **mapRange** \u002F **normalize** handle units; they work on numbers. Use **getUnit** \u002F **unitize** when units matter.\n- ❌ Override or rely on undocumented behavior; stick to the documented API.\n\n### Learn More\n\nhttps:\u002F\u002Fgsap.com\u002Fdocs\u002Fv3\u002FHelperFunctions\n",{"od":44,"name":5,"license":14,"triggers":47,"description":52},{"mode":38,"category":45,"upstream":46},"animation-motion","https:\u002F\u002Fgithub.com\u002Fgreensock\u002Fgsap-skills",[19,48,49,50,51],"clamp animation value","maprange","snap animation","gsap random","Official GSAP skill for gsap.utils — clamp, mapRange, normalize, interpolate, random, snap, toArray, wrap, pipe. Use when the user asks about gsap.utils, clamp, mapRange, random, snap, toArray, wrap, or helper utilities in GSAP.\n","main","f19b254e8975d0bfddb394686706106930d7964d","Web-Design\u002Ffrontend-and-motion-implementation\u002Fopen-design-gsap-utils","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus","https:\u002F\u002Fgithub.com\u002Fendman100","2026-11-12 18:13:37",{"source":8,"skillName":5,"commands":60,"prompt":70,"zipAvailable":71},[61,64,67],{"tool":62,"command":63},"npx","npx skills add endman100\u002Fskill-router-nexus --skill gsap-utils",{"tool":65,"command":66},"bunx","bunx skills add endman100\u002Fskill-router-nexus --skill gsap-utils",{"tool":68,"command":69},"pnpm","pnpm dlx skills add endman100\u002Fskill-router-nexus --skill gsap-utils","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FWeb-Design\u002Ffrontend-and-motion-implementation\u002Fopen-design-gsap-utils\u002FSKILL.md",true,[],[74,98,134,155,164,188],{"skillNo":75,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":78,"sourceHtmlUrl":79,"categories":80,"keywords":86,"publishedAt":39},"01M6MPCT5BXVER8HQZTW3QE9AS","create-master","基于佛教经典文献，生成特定高僧大德的 AI 教学角色","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FMetaphysics-and-Spirituality\u002FMaster-skill\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FMetaphysics-and-Spirituality\u002FMaster-skill\u002FSKILL.md",[81],{"categoryNo":82,"categoryName":83,"taxonomyType":84,"taxonomyTypeDesc":85},"01JBSEEDCAT000000000000039","教师与教育","PROFESSION","适用职业",[87,88,89,90,91,92,93,94,95,96,97],"create master","master","create","生成","true","webfetch","edit","write","read","grep","Bash",{"skillNo":99,"name":100,"nameZh":6,"description":101,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":102,"sourceHtmlUrl":103,"categories":104,"keywords":116,"publishedAt":39},"01M6M43AKE95Y64E1JRXEF5QQ3","writing-dna-skill","从至少 20 篇完整文章中蒸馏可复用的写作 DNA，分析语言、文章结构、选题逻辑、素材策略、认知框架和视觉风格，并生成 Writing-DNA.md；按该 DNA 写作时会读取全部蒸馏产物和 5 篇相关原文。用于中英文作者、账号、品牌或出版物的风格分析与一致性写作。 Distill reusable Writing DNA from at least 20 complete articles for Chinese or English authors, publications, brands, and accounts; use for language, structure, topic logic, source strategy, cognitive-frame, and visual-style analysis.","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FWriting-and-Content\u002Fwriting-dna-skill\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FWriting-and-Content\u002Fwriting-dna-skill\u002FSKILL.md",[105,110,113],{"categoryNo":106,"categoryName":107,"taxonomyType":108,"taxonomyTypeDesc":109},"01JBSEEDCAT000000000000018","写作与文案","SCENARIO","使用场景",{"categoryNo":111,"categoryName":112,"taxonomyType":108,"taxonomyTypeDesc":109},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":114,"categoryName":115,"taxonomyType":84,"taxonomyTypeDesc":85},"01JBSEEDCAT000000000000036","内容创作者",[117,118,119,120,121,122,123,124,125,126,34,127,128,90,129,130,131,24,132,133],"writing dna skill","DNA","writing","strategy","english","logic","visual","structure","chinese","reusable","style","distill","analysis","frame","source","at","complete",{"skillNo":135,"name":136,"nameZh":6,"description":137,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":138,"sourceHtmlUrl":139,"categories":140,"keywords":143,"publishedAt":39},"01M6M428TTCGQ4ME3KY99VN037","stop-slop","Remove AI writing patterns from prose. Use when drafting, editing, or reviewing text to eliminate predictable AI tells.","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FWriting-and-Content\u002Fstop-slop\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FWriting-and-Content\u002Fstop-slop\u002FSKILL.md",[141,142],{"categoryNo":106,"categoryName":107,"taxonomyType":108,"taxonomyTypeDesc":109},{"categoryNo":114,"categoryName":115,"taxonomyType":84,"taxonomyTypeDesc":85},[144,145,146,147,22,148,36,149,150,34,151,152,153,24,154,119],"slop","stop slop","stop","drafting","drafts","patterns","prose","remove","editing","text","content",{"skillNo":156,"name":157,"nameZh":6,"description":158,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":159,"sourceHtmlUrl":160,"categories":161,"keywords":162,"publishedAt":39},"01M6M41X0B7EBX42TK435DMGGR","shuorenhua","检查和清理中英文文本里的 AI 套路，适用于“去 AI 味”“说人话”“自然一点”“别像模板”“先标问题”这类改写和审稿需求；按场景控制力度，同时保留事实、术语、语域和责任主体。","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FWriting-and-Content\u002Fshuorenhua\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FWriting-and-Content\u002Fshuorenhua\u002FSKILL.md",[],[157,163],"文本",{"skillNo":165,"name":166,"nameZh":6,"description":167,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":168,"sourceHtmlUrl":169,"categories":170,"keywords":171,"publishedAt":39},"01M6M3ZD12WBEW5KXKDM4N6DFG","naming","Name products, SaaS, brands, open source projects, bots, and apps. Use when the user needs to name something, find a brand name, or pick a product name. Metaphor-driven process that produces memorable, meaningful names and avoids AI slop.","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FWriting-and-Content\u002Fnaming-main\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FWriting-and-Content\u002Fnaming-main\u002FSKILL.md",[],[166,172,173,174,175,176,34,177,95,131,178,179,180,181,97,182,183,184,185,22,186,187,144],"repo","websearch","product name","apps","bots","view","brand","pick","gh","projects","open","saas","open source","product","describe","ai slop",{"skillNo":189,"name":190,"nameZh":6,"description":191,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":192,"sourceHtmlUrl":193,"categories":194,"keywords":196,"publishedAt":39},"01M6M3YVXAFAAWJ7F6JMPFREYE","humanizer-zh","去除文本中的 AI 生成痕迹。适用于编辑或审阅文本，使其听起来更自然、更像人类书写。\n基于维基百科的\"AI 写作特征\"综合指南。检测并修复以下模式：夸大的象征意义、\n宣传性语言、以 -ing 结尾的肤浅分析、模糊的归因、破折号过度使用、三段式法则、\nAI 词汇、否定式排比、过多的连接性短语。","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FWriting-and-Content\u002Fhumanizer-zh\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fendman100\u002Fskill-router-nexus\u002Fblob\u002Fmain\u002FWriting-and-Content\u002Fhumanizer-zh\u002FSKILL.md",[195],{"categoryNo":106,"categoryName":107,"taxonomyType":108,"taxonomyTypeDesc":109},[197,198,199,95,94,93,119,90,163,200,144,146],"humanizer","zh","humanizer zh","翻译"]