Shapes
A Shape is one Element: the smallest thing motly draws. Its Spec is plain JSON with a kind and
that kind’s fields. Draw one alone with gsap.effects.shape() or core’s Shape, or put it in a
Burst’s children to draw many.
Every kind is drawn centred on its position and, at angle 0, pointing at 12 o’clock. The examples
on this page repeat forever with GSAP’s repeat: -1, so you can watch them without clicking.
Each field takes a single value or Keyframes, an array that moves from one
value to the next over the Element’s duration, and either can be handed out across a Burst’s
Children with each(). The types say where: a circle’s Spec rejects
points, and a star’s requires it.
Fields every kind takes
Section titled “Fields every kind takes”| Field | Takes | If left out |
|---|---|---|
duration |
a time: seconds, or a string such as '400ms' |
1 |
delay |
a time to wait before the first frame | 0 |
restAt |
a progress from 0 to 1 | the last frame |
angle |
an angle, clockwise: degrees, or a string such as '0.5turn' |
0 |
scale |
a number | 1 |
opacity |
a number from 0 to 1 | 1 |
fill |
a color | deeppink; none on a cross, line or zigzag |
stroke |
a color | none; deeppink on a cross, line or zigzag |
strokeWidth |
a length: pixels, as a number or a string such as '4px' |
0; 2 on a cross, line or zigzag |
easing |
a Curve, or one per property | linear |
A cross, a line and a zigzag enclose nothing, so they are stroked rather than filled unless you say otherwise. Each style field you leave out takes its kind’s default, whatever the others say.
restAt is the Resting frame: the one still frame a viewer who
prefers reduced motion sees instead of the motion. It is read from the Spec you create the Instance
from, not from a Child’s. duration and delay are covered on the time page.
import { Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// The fields every kind takes. Each one here is Keyframes, so each one moves.const spec = { kind: 'polygon', points: 4, radius: 40, angle: [0, 90], scale: [0.5, 1.5], opacity: [1, 0.3], fill: ['deeppink', 'gold'], stroke: 'white', strokeWidth: [0, 6], duration: 1.2, restAt: 0.5,};
gsap.effects.shape('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>circle
Section titled “circle”For dots, rings (with fill: 'none' and a stroke) and ripples.
| Field | Takes | If left out |
|---|---|---|
radius |
a length | 50 |
import { Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// A ring: a circle with no fill and a stroke.const spec = { kind: 'circle', radius: [0, 90], fill: 'none', stroke: 'deeppink', strokeWidth: [16, 0], duration: 1, restAt: 0.4,};
gsap.effects.shape('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>polygon
Section titled “polygon”For triangles, squares and hexagons: any regular shape with straight sides.
| Field | Takes | If left out |
|---|---|---|
points |
how many corners, 3 or more. The first is at 12 o’clock. | required |
radius |
a length, from the centre to each corner | 50 |
points holds still for the Element’s whole life: it can be handed out with each(), but it is
not Keyframes.
import { Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
const spec = { kind: 'polygon', points: 6, radius: [20, 90], angle: [0, 60], fill: 'none', stroke: 'gold', strokeWidth: 4, opacity: [1, 0], duration: 1.2, restAt: 0.4,};
gsap.effects.shape('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>For sparkles and celebration bursts.
| Field | Takes | If left out |
|---|---|---|
points |
how many tips, 2 or more. The first is at 12 o’clock. | required |
radius |
a length, from the centre to each tip | 50 |
innerRadius |
how far in the notches sit, as a fraction of radius: 0 is spikes, 1 a polygon with twice the corners |
0.5 |
As a fraction, innerRadius keeps a star’s shape while its radius animates.
import { Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// innerRadius is a fraction of radius: 0.2 is spiky, 0.8 is nearly a polygon.const spec = { kind: 'star', points: 6, radius: 80, innerRadius: [0.2, 0.8, 0.2], angle: [0, 60], fill: 'gold', duration: 1.6, restAt: 0.25,};
gsap.effects.shape('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>For a plus sign, or an x when turned 45°.
| Field | Takes | If left out |
|---|---|---|
radius |
a length, from the centre to the end of each arm | 50 |
import { Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// A cross encloses nothing, so it is stroked by default: deeppink, 2 px wide.const spec = { kind: 'cross', radius: [10, 60], angle: [0, 90], strokeWidth: [10, 0], duration: 0.9, restAt: 0.4,};
gsap.effects.shape('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>For streaks and rays. A line runs from 12 o’clock to 6; turn it with angle.
| Field | Takes | If left out |
|---|---|---|
radius |
a length, from the centre to each end | 50 |
In a Burst, give the Burst orient: true to turn each line
along its throw; otherwise its angle is its own, like every Child’s.
import { Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// A line runs from 12 o'clock to 6; angle turns it.const spec = { kind: 'line', radius: 80, angle: [0, 180], stroke: ['#06d6a0', '#118ab2'], strokeWidth: 6, duration: 1.2, restAt: 0.25,};
gsap.effects.shape('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>zigzag
Section titled “zigzag”For sparks and squiggles. A zigzag runs from 12 o’clock to 6.
| Field | Takes | If left out |
|---|---|---|
points |
how many corners, ends included, 2 or more, evenly spaced along the length | required |
radius |
a length, from the centre to each end | 50 |
amplitude |
a length: how far each corner between the ends swings to either side | a quarter of radius |
import { Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// Turned 90° to run left to right; amplitude is how far each corner swings.const spec = { kind: 'zigzag', points: 9, radius: 110, angle: 90, amplitude: [0, 24, 0], stroke: '#ffd166', strokeWidth: 4, duration: 1.4, restAt: 0.5,};
gsap.effects.shape('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>For any outline the other kinds do not draw, such as a heart.
| Field | Takes | If left out |
|---|---|---|
d |
an SVG path, drawn in a 100×100 box centred on (50, 50), as copied out of a design tool | required |
radius |
a length: half the width of that box once drawn, so 50 draws the path at the size it was written |
50 |
Like points, d holds still: hand different paths out with each(), but do not animate one
path into another.
import { Motly } from '@motly/gsap';import { gsap } from 'gsap';
gsap.registerPlugin(Motly);
// Any SVG path, written in a 100×100 box centred on (50, 50). radius 50 draws it at that size.const heart = 'M50 88C22 66 6 50 6 32C6 18 17 8 30 8C39 8 46 13 50 20C54 13 61 8 70 8C83 8 94 18 94 32C94 50 78 66 50 88Z';
const spec = { kind: 'path', d: heart, radius: [20, 70], fill: '#ff4d6d', opacity: [1, 0], duration: 1.1, restAt: 0.3,};
gsap.effects.shape('.origin', { spec, repeat: -1, repeatDelay: 0.5 });<div class="origin"></div>