Skip to main content

Shapes

MotionScript provides seven shape nodes: Rect, Ellipse, Line, Path, Polygon, Polygram, and Image. All shapes support fill, stroke, shadow, opacity, position, size, and effects.

Common props

Every shape inherits these from Node and ShapeNode:

PropTypeDefaultDescription
xnumber0Horizontal offset from layout position
ynumber0Vertical offset from layout position
widthnumber | 'fill' | 'hug''fill'Width: fixed pixels, expand to parent, or shrink to content
heightnumber | 'fill' | 'hug''fill'Height
scalenumber1Uniform scale multiplier
rotatenumber0Rotation in degrees
opacitynumber1Transparency (0–1)
fillFillProp | FillProp[][]Fill color(s) or gradient(s)
strokeStrokeProp | StrokeProp[][]Stroke(s)
shadowShadowProp | ShadowProp[][]Drop shadow(s)
effectsEffectChain | SceneEffect[][]Post-process effects (blur, grayscale, pixelate)
paddingnumber | PaddingProps0Inner spacing
clipbooleanfalseClip children to this shape's outline

start and end

Every shape also accepts start and end (both 01). They control what portion of the shape's outline is drawn — useful for draw-on animations:

// Draw a circle from 0% to 100% over 1.5 seconds
yield* circle().to({ end: 1 }, 1.5);

Rect

The primary building block. Rect draws a rounded rectangle and can also act as a flex layout container for its children.

import { Scene, Rect, createRef, wait } from '@motion-script/core';

export class MyScene extends Scene {
*build() {
const box = createRef<Rect>();

this.add(
<Rect
ref={box}
width={300}
height={200}
fill="royalblue"
borderRadius={16}
/>
);

yield* wait(2);
}
}

Rect-specific props

PropTypeDefaultDescription
borderRadiusnumber | BorderRadiusProps0Corner rounding
group'row' | 'column' | 'stack''row'Layout mode for children
gapnumber | 'auto'0Spacing between children
alignment{ x: number, y: number }{ x: 0, y: 0 }Child alignment (-1 to 1 per axis)

Per-corner border radius

<Rect
width={200}
height={200}
fill="hotpink"
borderRadius={{ topLeft: 0, topRight: 40, bottomLeft: 40, bottomRight: 0 }}
/>

Ellipse

Draws circles, ellipses, and arcs. Use startAngle and sweep to create pie slices or progress rings.

import { Scene, Ellipse, createRef, wait } from '@motion-script/core';

export class MyScene extends Scene {
*build() {
const arc = createRef<Ellipse>();

this.add(
<Ellipse ref={arc} width={200} height={200} fill="tomato" sweep={0} />
);

// Animate from 0° to 360° (draw the full circle)
yield* arc().to({ sweep: 360 }, 1.5);
}
}

Ellipse-specific props

PropTypeDefaultDescription
startAnglenumber0Starting angle in degrees
sweepnumber360Arc sweep in degrees (360 = full circle)
rationumber1Width/height ratio (stretch the ellipse)

Line

A polyline connecting an array of { x, y } points. Set closed: true to close the path back to the first point.

import { Scene, Line, wait } from '@motion-script/core';

export class MyScene extends Scene {
*build() {
this.add(
<Line
points={[{ x: -150, y: 0 }, { x: 0, y: -100 }, { x: 150, y: 0 }]}
stroke={{ fill: 'white', weight: 4 }}
radius={20}
/>
);

yield* wait(2);
}
}

Line-specific props

PropTypeDefaultDescription
points{ x: number, y: number }[][]Vertices of the line
radiusnumber0Corner rounding at each vertex
closedbooleanfalseConnect the last point back to the first

Path

Renders any SVG-style path string. The node auto-measures its bounds and defaults to 'hug' sizing.

import { Scene, Path, wait } from '@motion-script/core';

export class MyScene extends Scene {
*build() {
this.add(
<Path
d="M 0 0 L 100 0 L 100 40 L 140 20 L 100 0 L 100 40"
fill="mediumpurple"
stroke={{ weight: 2, fill: 'white' }}
/>
);

yield* wait(2);
}
}

Path-specific props

PropTypeDescription
dstring | PathCommand[]SVG path data string or command array

Polygon

A regular polygon with any number of sides. sides: 3 is a triangle, sides: 6 is a hexagon.

import { Scene, Polygon, createRef, easeOutElastic } from '@motion-script/core';

export class MyScene extends Scene {
*build() {
const hex = createRef<Polygon>();

this.add(
<Polygon ref={hex} sides={6} width={200} height={200} fill="teal" />
);

yield* hex().to({ rotate: 60 }, 1, easeOutElastic);
}
}

Polygon-specific props

PropTypeDefaultDescription
sidesnumber5Number of sides
borderRadiusnumber0Corner rounding

Polygram

A star polygon. ratio controls the depth of the points — lower values produce sharper stars.

import { Scene, Polygram, createRef } from '@motion-script/core';

export class MyScene extends Scene {
*build() {
const star = createRef<Polygram>();

this.add(
<Polygram ref={star} sides={5} ratio={0.4} width={300} height={300} fill="gold" borderRadius={10} />
);

yield* star().to({ rotate: 360 }, 2);
}
}

Polygram-specific props

PropTypeDefaultDescription
sidesnumber5Number of points on the star
rationumber0.5Inner/outer radius ratio (lower = sharper points)
borderRadiusnumber0Corner rounding

Image

Renders an image file with configurable fit mode and optional media filters.

import { Scene, Image, createRef, wait } from '@motion-script/core';

export class MyScene extends Scene {
*build() {
this.add(
<Image src="./photo.jpg" fit="fill" width={800} height={450} borderRadius={20} />
);

yield* wait(2);
}
}

Image-specific props

PropTypeDefaultDescription
srcstringPath to the image file
fit'fill' | 'fit' | 'crop' | 'tile'How the image fills the node
borderRadiusnumber | BorderRadiusProps0Corner rounding
filtersMediaFilter[] | FilterChain[]Image filters (see Image Filters)
scalingnumberScale multiplier applied to the image
transformnumber[][]Raw matrix transformation

Fills

Every shape accepts a fill prop. Pass a CSS color string for quick use, or a fill object for gradients and images.

// CSS color string (shorthand)
<Rect fill="royalblue" />

// Solid color object
<Rect fill={{ type: 'color', color: '#4f80ff' }} />

// Linear gradient
<Rect fill={{ type: 'linear-gradient', colors: ['#4f80ff', '#e84393'], stops: [0, 1] }} />

// Radial gradient
<Rect fill={{ type: 'radial-gradient', colors: ['white', 'transparent'], radius: 200 }} />

// Multiple fills (layered bottom to top)
<Rect fill={[
{ type: 'color', color: '#0f1117' },
{ type: 'linear-gradient', colors: ['#4f80ff33', 'transparent'] }
]} />

Fill types

TypeKey props
'color'color (CSS string or RGBA array), opacity, blend
'linear-gradient'colors, stops, start {x,y}, end {x,y}
'radial-gradient'colors, stops, center {x,y}, radius
'conic-gradient'colors, stops, center {x,y}, startAngle
'image'src, mode (fill/fit/crop/tile), filters, blend

Stroke

// Simple white stroke
<Rect stroke={{ weight: 3, fill: 'white' }} />

// Dashed stroke
<Rect stroke={{ weight: 2, fill: '#aaa', dash: [10, 6] }} />

// Animated dash offset (draw-on effect)
yield* rect().to({ stroke: { dashOffset: 100 } }, 1);
PropTypeDefaultDescription
weightnumber1Stroke width in pixels
fillFillPropStroke color or gradient
dashnumber | number[]Dash pattern (e.g. [10, 5])
dashOffsetnumber0Offset into the dash pattern

Shadow

<Rect shadow={{ blur: 20, fill: 'black', opacity: 0.4, dx: 0, dy: 8 }} />

// Multiple shadows
<Rect shadow={[
{ blur: 10, fill: 'black', opacity: 0.3, dx: 5, dy: 5 },
{ blur: 30, fill: '#4f80ff', opacity: 0.2, dx: 0, dy: 0 },
]} />