Motion graphics
Draw with shapes, like in a motion-graphics video: stars that pop in, arrows that draw themselves, planets in orbit, a rocket on a route. Plain JSON, with an optional GSAP script for anything more.
A motion scene is a list of shapes. Each shape says what it is, where it sits, what colour it has, and how it comes in, keeps moving and leaves. The narration drives the timing: lines are the passages that are spoken, and a shape appears when its line starts. Everything is written as data, so a person or an AI can write it without knowing GSAP.
{
"kind": "motion",
"heading": "Launch day",
"shapes": [
{
"id": "star",
"type": "star",
"size": 3,
"x": 80,
"y": 7,
"fill": "amber",
"repeat": {
"count": 9,
"gap": 16
},
"enter": "pop",
"loop": "blink",
"at": 0.3
},
{
"id": "trail",
"type": "path",
"d": "M 14 50 C 50 54, 80 6, 146 12",
"stroke": "sky",
"strokeWidth": 0.8,
"enter": "draw",
"at": "line1",
"duration": 1.6
},
{
"id": "rocket",
"type": "triangle",
"width": 7,
"height": 10,
"x": 14,
"y": 50,
"fill": "rose",
"glow": true,
"enter": "pop",
"at": "line2"
},
{
"id": "label",
"type": "text",
"text": "Lift-off!",
"size": 7,
"x": 118,
"y": 42,
"fill": "text",
"enter": "type",
"at": "line3"
}
],
"script": "tl.to(\"rocket\", { motionPath: { path: \"trail\", autoRotate: 90 }, duration: 2.6, ease: \"power1.inOut\" }, \"line2+=0.4\");",
"lines": [
{
"say": "Every launch starts with a plan, drawn out on the board."
},
{
"say": "Then the rocket takes its place at the start of the route."
},
{
"say": "And off it goes, all the way to lift-off."
}
]
}
The canvas
Shapes are placed on a drawing board that is scaled to the video, so a drawing looks the same at every size. One unit is one percent of the video's width. x goes to the right and y goes down, both from the top left corner, and a shape's x,y is its centre.
| canvas | Width × height | Use it for |
|---|---|---|
wide | 160 × 60 | A landscape video (the default). |
square | 100 × 100 | A square video, or a drawing in the middle of a scene. |
tall | 60 × 100 | A portrait video. |
Shapes
Only id and type are required; a shape with nothing else sits in the middle of the canvas, 16 units wide, in the accent colour. Shapes are drawn from the back to the front, in the order of the list (up to 40).
{
"id": "badge",
"type": "star",
"x": 40,
"y": 30,
"size": 14,
"points": 6,
"fill": "amber",
"fill2": "orange",
"glow": true,
"enter": "pop",
"loop": "pulse",
"at": "line2"
}
| type | What it draws |
|---|---|
rect | A rectangle. width and height set its sides, radius rounds the corners. |
square | A square of size. radius rounds the corners. |
circle | A circle across size. |
ellipse | An oval: width by height. |
triangle | A triangle pointing up. Turn it with rotation. |
diamond | A rhombus: a square standing on its corner. |
polygon | A regular polygon. sides from 3 to 12 (default 6). |
star | A star. points from 3 to 16 (default 5), inner sets how deep it is cut. |
heart | A heart. |
arrow | A line from x,y to x2,y2 with an arrow head at its end. fill is its colour, strokeWidth its thickness. |
line | A plain line from x,y to x2,y2. |
ring | A circle drawn as an outline only, strokeWidth thick. |
cross | A plus sign. inner sets how thin its arms are. |
text | Words, centred on x,y. size is the font size, weight the boldness. Plain words only. |
path | Any SVG path in d, in canvas units, drawn from x,y. Use it for curves, routes and orbits; a script can move other shapes along it. |
Colours
fill, fill2 and stroke take a colour in any of these forms:
- a hex colour:
#ff6b6bor#f66; - a colour of the theme, which follows the look of the video:
violet,emerald,amber,rose,sky,fuchsia,teal,orange, each also as-lightand-deep(sky-deep); accentandaccent2(the two main colours of the theme),text(the colour of the text),white,black;nonefor no colour at all (an outline without an inside).
fill2 turns the fill into a gradient from fill to fill2, glow: true adds a soft glow in the colour of the shape, and opacity makes it see-through.
Movement
A shape moves with three words, all optional: enter (how it arrives), loop (what it keeps doing while it is there) and exit (how it leaves, at exitAt). duration sets how long the arrival and the exit take and delay adds a wait. A shape with no enter is simply there from the start.
enter
| enter | What it does |
|---|---|
fade | Fades in. |
pop | Grows from nothing with a small overshoot. |
rise | Floats up a little while fading in. |
drop | Falls from above and bounces. |
slide-left | Slides in from the left. |
slide-right | Slides in from the right. |
zoom | Shrinks into place from a large size. |
spin | Turns half a circle while growing. |
grow | Grows upward from its bottom edge: bars and columns. |
draw | A line, arrow or path draws itself; a filled shape fills in once its outline is drawn. |
type | A text is typed out letter by letter. |
loop
| loop | What it does |
|---|---|
float | Drifts up and down, slowly. |
pulse | Swells and shrinks, like a heartbeat. |
spin | Turns round and round. |
sway | Rocks from side to side. |
bounce | Hops up and down. |
blink | Fades down and up. |
wiggle | Shakes a little. |
exit
| exit | What it does |
|---|---|
fade | Fades out. |
shrink | Shrinks to nothing. |
slide-left | Slides out to the left. |
slide-right | Slides out to the right. |
slide-up | Floats up and away. |
slide-down | Sinks down and away. |
Timing
at says when a shape comes in. It is either a number of seconds from the start of the scene, or a narration moment: line1 is when the first entry of lines starts to be spoken, line2 the second, and so on. Tying shapes to lines keeps the picture in step with the voice, whatever the speed of the narrator. Shapes without at come in one after another, a quarter of a second apart.
Many copies
repeat draws a shape many times, in a row, a column, a grid, a circle or along a diagonal, around its own x,y. The copies are named dot1, dot2 ... and all belong to the group dot, so a script can move them together. stagger is the delay between one copy and the next, and palette gives them colours in turn.
{
"id": "dot",
"type": "circle",
"size": 4,
"x": 80,
"y": 30,
"repeat": {
"count": 12,
"layout": "circle",
"radius": 18,
"palette": [
"rose",
"amber",
"emerald",
"sky"
]
},
"enter": "pop",
"stagger": 0.1
}
| layout | Where the copies go |
|---|---|
row | Copies side by side, gap apart. |
column | Copies one under the other. |
grid | Rows and columns; columns sets how many per row. |
circle | Copies round a ring of radius (startAngle sets where it starts, rotate turns them outwards). |
diagonal | Copies along a slanting line. |
A scene can hold up to 120 shapes once the copies are counted. The layers of neurons below are three shapes with repeat, one column of copies each; the script sends a signal through them.
The GSAP script
For choreography the presets cannot give, a scene can carry a script: a GSAP timeline written as text. Only calls of the timeline tl are understood, never other JavaScript, so a script can move shapes and nothing else. Every call has the same shape: tl.to(target, { properties }, position).
tl.from("bar", { scaleY: 0, duration: 0.8, stagger: 0.15, ease: "back.out(1.7)" }, "line2");
tl.to("rocket", { motionPath: { path: "route", autoRotate: true }, duration: 3 }, "line3+=0.5");
tl.to("sun", { rotation: 360, duration: 8, ease: "none", repeat: -1 }, 0);
tl.to("label", { fill: "rose", scale: 1.4, yoyo: true, repeat: 3 }, "<");
- Calls:
tl.to,tl.from,tl.fromTo,tl.set,tl.addLabel. - Targets: the
idof a shape, the name of a group (the copies of arepeat),"all", or a list of names. - Position (the last argument): seconds, a label such as
"line2","line2+=0.5"for half a second after it, or"<"to start with the previous animation. motionPathmoves a shape along another shape (apathis the usual choice);autoRotateturns it to face the way it goes.repeat: -1repeats until the scene ends.yoyo: trueplays it back and forth.
Properties a script may set: x, y, xPercent, yPercent, rotation, scale, scaleX, scaleY, skewX, skewY, opacity, autoAlpha, motionPath, fill, stroke, strokeWidth, fillOpacity, strokeOpacity, drawSVG, text, duration, delay, ease, stagger, repeat, repeatDelay, yoyo, immediateRender. Anything else is reported with the line it is on and what is allowed, and the rest of the script still runs.
The earth below travels round the sun with one line of script:
Every field of a shape
| Field | Type | What it does |
|---|---|---|
| └ idrequired | string | Name of the shape. The script refers to it by this name. |
| └ typerequired | enum | What to draw.
|
| └ group | string | A name shared by several shapes, so the script can move them together. |
| └ x | number | Centre of the shape across the canvas. Default: the middle. A Limits: -400–400 |
| └ y | number | Centre of the shape down the canvas. Default: the middle. Limits: -400–400 |
| └ size | number | Width and height of the shape (font size for Limits: 0–400 |
| └ width | number | Overrides the width of Limits: 0–400 |
| └ height | number | Overrides the height, like Limits: 0–400 |
| └ x2 | number | Where a Limits: -400–400 |
| └ y2 | number | Where a Limits: -400–400 |
| └ fill | string | Colour inside the shape. Default |
| └ fill2 | string | A second colour: the fill becomes a gradient from |
| └ stroke | string | Colour of the outline. |
| └ strokeWidth | number | Thickness of the outline or line. Default 1 for lines, 2 for a Limits: 0–40 |
| └ opacity | number | 0 is invisible, 1 solid (default). Limits: 0–1 |
| └ rotation | number | Degrees, clockwise. Limits: -3600–3600 |
| └ radius | number | Rounded corners of a Limits: 0–400 |
| └ sides | integer | Corners of a Limits: 3–12 |
| └ points | integer | Points of a Limits: 3–16 |
| └ inner | number | How deep a Limits: 0.1–0.9 |
| └ text | string | The words of a Limits: 1–60 characters |
| └ weight | integer | Boldness of Limits: 100–900 |
| └ d | string | SVG path data in canvas units, for a Limits: up to 600 characters |
| └ glow | boolean | A soft glow in the colour of the shape. |
| └ repeat | object | Draw many copies of this shape in a row, grid or circle. |
| └ countrequired | integer | How many copies. They are named Limits: 2–60 |
| └ layout | enum | Where the copies go, around the shape's own position. Default
|
| └ gap | number | Distance between the centres of neighbouring copies. Default: 1.5 times the size. Limits: 0–400 |
| └ columns | integer | Copies per row in a Limits: 1–20 |
| └ radius | number | Radius of a Limits: 0–400 |
| └ startAngle | number | Where a Limits: -360–360 |
| └ palette | string[] | Colours the copies take in turn, instead of Limits: 1–8 items |
| └ rotate | boolean | Turn each copy of a |
| └ enter | enum | How the shape comes in. Without it the shape is simply there from the start.
|
| └ loop | enum | A movement that repeats while the shape is on screen.
|
| └ exit | enum | How the shape leaves, at
|
| └ at | number | string | When the shape comes in: seconds, or Limits: 0–600 |
| └ delay | number | Extra seconds before Limits: 0–600 |
| └ duration | number | Seconds Limits: 0.05–30 |
| └ stagger | number | Seconds between the copies of a Limits: 0–5 |
| └ exitAt | number | string | When the shape leaves, in the same terms as Limits: 0–600 |
The scene around the shapes (heading, lead, lines, canvas, script) is listed in the scene reference. Maps, journeys and timelines have scenes of their own: worldmap, journey and timetravel are described there too.