Values
Every field on the Shapes, Burst and Swirl pages takes one
of the values on this page. A Spec stays plain JSON whatever it holds: JSON.stringify it, store
it, and pass it back in, and it draws the same thing.
Keyframes
Section titled “Keyframes”An array is Keyframes: successive values spread evenly over the Element’s duration. Two values move from the first to the second; four values reach the second a third of the way through, and so on.
import { Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// Four radius Keyframes and three fill Keyframes, each spread evenly over the 2 seconds.const spec = { kind: 'circle', radius: [10, 70, 30, 90], fill: ['deeppink', 'gold', '#06d6a0'], duration: 2, restAt: 0.5,};
gsap.effects.shape('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>Every animated field takes Keyframes: lengths, angles, numbers and colors. A field that holds still
for the Element’s whole life, such as a polygon’s points or a path’s d, does not. There is no
{ from: to } syntax: write [from, to].
An array always means Keyframes, as it does in GSAP and Motion. To give each Child of a Burst a
different value, use each(), below.
Descriptors
Section titled “Descriptors”rand() and each() are Descriptors: small tagged objects that stay JSON inside the Spec and are
resolved only when the Spec is drawn. Both are exported from @motly/core and @motly/gsap, and
with script tags they are Motly.rand and Motly.each.
rand(min, max)
Section titled “rand(min, max)”A number drawn between min and max, separately for each Instance and each Child. Use it
wherever a number should vary from one Child to the next: sizes, spins, durations, delays, a
Burst’s radius. Inside Keyframes each rand() draws its own number, so [rand(4, 14), 0] gives
each Child its own starting size. count, points and restAt take a plain number only.
import { Motly, rand } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// Every Child draws its own size, spin and duration. The Seed stays the same for the whole tween,// so each repeat is identical; Replay starts a new tween with a new Seed.const spec = { kind: 'burst', count: 14, radius: [0, rand(80, 120)], restAt: 0.4, children: { kind: 'star', points: 5, radius: [rand(4, 14), 0], angle: [0, rand(-360, 360)], fill: 'gold', duration: rand(0.6, 1.4), },};
gsap.effects.burst('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>In JSON, rand(4, 14) is { "__motly": "rand", "min": 4, "max": 14 }, which a design tool can
write too.
The Seed
Section titled “The Seed”Every rand() resolves from the Instance’s Seed. With the same Spec and the same Seed, motly
draws exactly the same thing, on every run and every machine. Pass seed to get that:
- In
@motly/gsap,seedinvars. The element or point at indexidraws fromseed + i. - In
@motly/core,seedbesiderendererin the second argument.
Without a Seed, each tween or Instance draws a random one and keeps it: a repeat, a restart and a scrub all show the same burst. The GSAP guide shows seeded and random bursts side by side.
each([...])
Section titled “each([...])”Hands values to a Burst’s Children in turn: the first value to the first Child, the second to the
second, and round again when the values run out. It works on any field of a Child, including
points, and on children itself, to mix kinds of Child.
import { each, Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// each() hands values out in turn: colors on one cycle of three, points on a cycle of two.const spec = { kind: 'burst', count: 12, radius: [0, 100], restAt: 0.4, children: { kind: 'star', points: each([4, 6]), radius: [12, 0], fill: each(['#ef476f', '#ffd166', '#118ab2']), duration: 1, },};
gsap.effects.burst('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>each() picks a value first, then any rand() in that value draws, so
each([rand(2, 4), rand(8, 12)]) alternates small and large Children of random sizes.
A plain number is pixels for a length, degrees for an angle, and seconds for a time. A string with a unit says otherwise:
| Kind of value | Plain number | Strings |
|---|---|---|
Length (radius, strokeWidth, amplitude) |
pixels | '40px' |
Angle (angle, a Swirl’s size) |
degrees | '90deg', '1.5rad', '0.5turn' |
Time (duration, delay, stagger) |
seconds | '0.4s', '400ms' |
scale, opacity, a star’s innerRadius and restAt are plain numbers.
import { Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// A plain number is px, degrees or seconds. A string names another unit.const spec = { kind: 'star', points: 5, radius: '70px', angle: [0, '1turn'], fill: 'none', stroke: '#ffd166', strokeWidth: 4, duration: '1500ms', restAt: 0.2,};
gsap.effects.shape('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>Colors
Section titled “Colors”A color that holds still can be any CSS color, including var(--brand) with the SVG Renderer.
Keyframes of colors are named colors, hex, rgb() or rgba(), since motly has to mix them: it
moves the red, green, blue and alpha from one Keyframe to the next together.
import { Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// Keyframed colors: named, hex, rgb() or rgba(). A single color can be any CSS color.const spec = { kind: 'polygon', points: 6, radius: 70, fill: ['tomato', '#ffd166', 'rgb(6, 214, 160)', 'rgba(17, 138, 178, 0.3)'], stroke: 'white', strokeWidth: 3, duration: 2, restAt: 0.4,};
gsap.effects.shape('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>'none' means no fill or no stroke. It cannot be a Keyframe, because there is nothing to mix it
with; fade with opacity instead.
The canvas Renderer only understands colors a canvas does, so no var() there.
Curves
Section titled “Curves”easing says how a property moves between its Keyframes. It is linear when left out. A Curve is
one of three things, all of them data:
- a CSS keyword:
'linear','ease','ease-in','ease-out','ease-in-out'; - a cubic-bezier, as four numbers:
[0.7, -0.4, 0.3, 1.4], which may overshoot; - an SVG path in a 100×100 box, as copied from a design tool, for a curve with more than one
bend: x is progress from 0 to 100 and y runs down, so it starts at
M0,100and ends at100,0.
The named curves are constants you import that hold one of these:
sine, quad, cubic, quart, quint, expo, circ and back as cubic-beziers, and
bounce and elastic as paths, each as In, Out and InOut, such as cubicOut or
bounceInOut.
import { bounceOut, cubicOut, Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// A Burst of one Child throws it straight up, so the Burst's easing is the dot's path in time.const curves = ['linear', cubicOut, [0.7, -0.4, 0.3, 1.4], bounceOut];
document.querySelectorAll('.origin').forEach((origin, index) => { const spec = { kind: 'burst', count: 1, radius: [0, 150], easing: curves[index], restAt: 1, children: { kind: 'circle', radius: 8, fill: '#ffd166', duration: 1.2 }, }; gsap.effects.burst(origin, { spec, repeat: -1, repeatDelay: 0.5 });});<main> <figure><div class="origin"></div><figcaption>'linear'</figcaption></figure> <figure><div class="origin"></div><figcaption>cubicOut</figcaption></figure> <figure><div class="origin"></div><figcaption>cubic-bezier</figcaption></figure> <figure><div class="origin"></div><figcaption>bounceOut</figcaption></figure></main>
<style> main { display: flex; gap: 1.5rem; } figure { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; width: 7rem; height: 200px; margin: 0; } figcaption { margin-top: 0.75rem; white-space: nowrap; opacity: 0.6; font: 0.8rem ui-monospace, monospace; }</style>A Burst’s easing moves its own radius, which is how the dots above travel. On a Shape,
easing is one Curve for every property, or one per property with default for the rest:
easing: { radius: bounceOut, opacity: 'ease-in', default: 'linear' }import { bounceOut, Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// A Curve per property, and `default` for the rest: radius bounces, opacity eases in.const spec = { kind: 'circle', radius: [10, 80], opacity: [1, 0.2], fill: ['deeppink', 'gold'], easing: { radius: bounceOut, opacity: 'ease-in', default: 'linear' }, duration: 1.4, restAt: 0.6,};
gsap.effects.shape('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>Under @motly/gsap, ease in vars is different: it warps the whole tween’s time on top of
every easing in the Spec. See the vocabulary rule.