distribute
Returns : Function
Returns a function to distribute an array of values based on the inputs that you give it.
Distributes an amount across the elements in an array according to various configuration options. Internally, it's what advanced staggers use, but you can apply it for any value. It essentially assigns values based on the element's position in the array (or in a grid):
// get a function that, when fed an index value, will return a value according to the configuration options
let distributor = gsap.utils.distribute({
// the base value to start from (default:0)
base: 50,
// total amount to distribute across the targets (this amount gets added to the "base" when returned)
amount: 100,
// position in the targets array to begin from (can be an index number, a keyword like "start", "center",
// "edges", "random", or "end", or an array of ratios along the x-axis and y-axis like [0.25, 0.75]) (default: 0)
from: "center",
// bases distribution on the element's position in a grid [rows, columns] instead of a flat array.
// You can also define the rows and columns in array format like [5, 10]
grid: "auto",
// for grid-based distributing, you can limit measurements to one axis ("x" or "y")
axis: "y",
// distributes based on an ease curve!
ease: "power1.inOut",
});
// get an array of all the elements with the class ".box" applied
let targets = gsap.utils.toArray(".box");
// Now for any target element, we can just feed in its index from the targets array (along with the target
// and array) and it'll do all the calculations and return the appropriate amount:
let distributedValue = distributor(2, targets[2], targets);
This can be used directly in a tween:
// animate the scale of all ".class" elements so that the ones in the middle are 0.5 and the ones on
// the outer edges are 3
gsap.to(".class", {
scale: gsap.utils.distribute({
base: 0.5,
amount: 2.5,
from: "center",
}),
});
Parameters
- config : Object - The config object to declare how you want inputs to be distributed. All properties inside of this object are optional. These properties can be used:
- base : Number - The base value to start from. The default is 0.
- amount : Number - The total amount to distribute across the targets (this amount gets added to the "base" when returned). So if
amountis1and there 100 targets, there would be a 0.01 difference between every return value. If you prefer to specify a certain amount between each target, use theeachproperty instead. - each : Number - The amount to add between each target (this amount gets added to the "base" when returned). So if
eachis1and the there are 4 targets, it would return 0, 1, 2, and 3. If you prefer to specify a total amount to split up among the targets, use theamountproperty instead. - from : [Number | String | Array] - The position in the targets array to begin from (can be an index number, a keyword like
"start","center","edges","random", or"end", or an array of ratios along the x-axis and y-axis like[0.25, 0.75]). The default is0. - grid : [String | Array] - Bases distribution on the element's position in a grid [rows, columns], like
[5, 10], instead of a flat array. You can use"auto"to have GSAP try to automatically detect the column and row count for DOM elements. - axis : String - For grid-based distributing, you can limit measurements to one axis (
"x"or"y"). - ease : Ease - Distributes based on an ease curve! The default is
"none".
This video on distribute that's part of SnorklTV's GSAP 3: Beyond the Basics course may help your understand.
And the companion pen used in the video.
<div id="demo">
<svg id="ease-vis" viewBox="0 0 650 650">
<defs>
<linearGradient id="macha" gradientUnits="userSpaceOnUse"
x1="29.1" y1="190.6" x2="620.9" y2="459.4">
<stop offset="20.74%" style="stop-color: var(--color-shockingly-green, #0ae448)" />
<stop offset="65.5%" style="stop-color: var(--color-lt-green, #abff84)" />
</linearGradient>
</defs>
<!-- bars are generated by JS -->
<g id="bars"></g>
<!-- y axis: positioned by gsap -->
<g id="markers">
<text x="0" y="0" fill="#fff">1</text>
<line x1="40" y1="0" x2="650" y2="0" stroke="#fff" />
<text x="0" y="0" fill="#fff">0.75</text>
<line x1="40" y1="0" x2="650" y2="0" stroke="#fff" />
<text x="0" y="0" fill="#fff">0.5</text>
<line x1="40" y1="0" x2="650" y2="0" stroke="#fff" />
<text x="0" y="0" fill="#fff">0.25</text>
<line x1="40" y1="0" x2="650" y2="0" stroke="#fff" />
<text x="0" y="0" fill="#fff">0</text>
<line x1="40" y1="0" x2="650" y2="0" stroke="#fff" />
</g>
</svg>
</div>/* GSAP brand: fonts, type sizes, colour vars, buttons and form controls.
Element selectors only, so a demo's own class-based styles still win. */
/* Fonts */
@font-face {
font-display: swap;
font-family: Mori;
font-weight: 400;
src: url(/fonts/Mori/PPMori-Regular.woff) format("woff");
}
@font-face {
font-display: swap;
font-family: Mori;
font-weight: 600;
src: url(/fonts/Mori/PPMori-SemiBold.woff) format("woff");
}
@font-face {
font-display: swap;
font-family: "Fraktion Mono";
font-weight: 400;
src: url(/fonts/Fraktion/PPFraktionMono-Bold.woff) format("woff");
}
/* Colours */
:root {
--color-shockingly-green: #0ae448;
--color-just-black: #0e100f;
--color-surface-white: #fffce1;
--color-pink: #fec5fb;
--color-shockingly-pink: #f100cb;
--color-orangey: #ff8709;
--color-lilac: #9d95ff;
--color-lt-green: #abff84;
--color-blue: #00bae2;
--color-grey: #191919;
--color-surface75: #bbbaa6;
--color-surface50: #7c7c6f;
--color-surface25: #42433d;
--gradient-macha: linear-gradient(114.41deg, var(--color-shockingly-green) 20.74%, var(--color-lt-green) 65.5%);
--gradient-orange-crush: linear-gradient(111.45deg, var(--color-orangey) 19.42%, #f7bdf8 73.08%);
--gradient-lipstick: linear-gradient(165.72deg, #f7bdf8 21.15%, #cd237f 81.93%);
--gradient-purple-haze: linear-gradient(153.58deg, #f7bdf8 32.25%, #2f3cc0 92.68%);
--gradient-skyfall: linear-gradient(131.77deg, #0a157a 30.82%, #15bfe4 81.82%);
--gradient-emerald-city: linear-gradient(166.9deg, var(--color-shockingly-green) 53.19%, #0085d0 107.69%);
--gradient-summer-fair: linear-gradient(144.02deg, var(--color-blue) 4.56%, var(--color-pink) 72.98%);
/* Short names many demos use */
--dark: var(--color-just-black);
--light: var(--color-surface-white);
--mid: var(--color-surface50);
--grey: var(--color-grey);
--gray: var(--color-grey);
--green: var(--color-shockingly-green);
--green-light: var(--color-lt-green);
--blue: var(--color-blue);
--purple: var(--color-lilac);
--pink: var(--color-pink);
--orange: var(--color-orangey);
--red: #cd237f;
/* Form controls */
--field-bg: #1c1d1f;
--field-border: var(--color-surface25);
--field-radius: 8px;
--focus-ring: 0 0 0 3px rgba(10, 228, 72, 0.35);
accent-color: var(--color-shockingly-green);
color-scheme: dark;
}
/* Type */
* { box-sizing: border-box; }
body {
margin: 0;
background-color: var(--color-just-black);
color: var(--color-surface75);
font-family: Mori, system-ui, sans-serif;
font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
line-height: 1.45;
-webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 {
margin: 0.5em 0;
color: var(--color-surface-white);
font-weight: 400;
line-height: 1.2;
}
h1 { font-size: clamp(2rem, 1.6rem + 2vw, 2.875rem); }
h2 { font-size: clamp(1.625rem, 1.4rem + 1.2vw, 2.2rem); }
h3 { font-size: clamp(1.375rem, 1.25rem + 0.6vw, 1.75rem); }
h4 { font-size: clamp(1.125rem, 1rem + 0.5vw, 1.4rem); }
a { color: inherit; text-underline-offset: 0.15em; }
code, pre, kbd { font-family: "Fraktion Mono", ui-monospace, Menlo, monospace; }
/* Buttons */
button,
input[type="button"],
input[type="submit"],
input[type="reset"] {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5em;
min-height: 2.5rem;
padding: 0 1.25rem;
border: 2px solid var(--color-surface75);
border-radius: 99px;
background: var(--color-just-black);
color: var(--color-surface75);
font: 600 0.9rem/1 Mori, system-ui, sans-serif;
cursor: pointer;
transition: border-color 0.2s, color 0.2s, background-color 0.2s;
}
button:hover,
input[type="button"]:hover,
input[type="submit"]:hover,
input[type="reset"]:hover {
border-color: var(--color-surface-white);
color: var(--color-surface-white);
}
button:disabled,
input:disabled { opacity: 0.4; cursor: not-allowed; }
/* Form controls */
label { color: var(--color-surface75); font-size: 0.9rem; }
input[type="text"],
input[type="number"],
input[type="email"],
input[type="search"],
input[type="url"],
input:not([type]),
select,
textarea {
min-height: 2.5rem;
padding: 0 0.75rem;
border: 1px solid var(--field-border);
border-radius: var(--field-radius);
background: var(--field-bg);
color: var(--color-surface-white);
font: 400 0.9rem/1.2 Mori, system-ui, sans-serif;
transition: border-color 0.2s, box-shadow 0.2s;
}
textarea { padding: 0.6rem 0.75rem; line-height: 1.45; }
input::placeholder,
textarea::placeholder { color: var(--color-surface50); }
input[type="checkbox"],
input[type="radio"] {
width: 1.1em;
height: 1.1em;
margin: 0 0.4em 0 0;
vertical-align: -0.15em;
}
input[type="range"] { width: min(100%, 18rem); }
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
outline: none;
border-color: var(--color-shockingly-green);
box-shadow: var(--focus-ring);
}
body {
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
body,
html {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
font-size: 20px;
}
svg {
overflow: visible;
width: 650px;
height: 650px;
}
.bar {
fill: url(#macha);
}
path {
stroke-width: 2px;
fill: none;
}
#demo {
margin-top: 50px;
text-align: center;
}createEaseVis();
gsap.set("svg", { scale: 0.75 });
gsap.set(".bar", { transformOrigin: "50% 100%" });
let end = gsap.utils.distribute({
base: 0.0,
amount: 0.5,
ease: "power2.in",
from: "edges"
});
gsap.to(".bar", {
scaleY: end
});
function createEaseVis() {
let svgNS = "http://www.w3.org/2000/svg";
let bars = document.getElementById("bars");
for (let i = 0; i < 65; i++) {
let rect = document.createElementNS(svgNS, "rect");
rect.setAttribute("width", 9);
rect.setAttribute("height", 650);
rect.setAttribute("x", i * 10);
rect.setAttribute("class", "bar");
bars.appendChild(rect);
}
gsap.set("text", {
y: gsap.utils.distribute({
base: 5,
amount: 650
})
});
gsap.set("line", {
y: gsap.utils.distribute({
base: 0,
amount: 650
}),
opacity: 0.4
});
}