Graphics

Graphics is the 2D drawing API. A node like Rect or Path gives you one shape with layout and props attached. A Graphics lets you record many shapes and paints into a single list and draw them as one figure.

import { Graphics } from 'motion-script';

const g = new Graphics()
  .ellipse({ width: 200, height: 200 })
  .fill('royalblue')
  .stroke({ weight: 4, fill: 'white' });

That builds a value. Nothing appears on screen until a node draws it, which is covered in Introduction.

When to use it

Use Graphics when the figure is not a tree of nodes:

  • Too many pieces to be nodes. A grid with 400 tick marks, a waveform, a scatter plot. Every node carries layout, signals and its own render scope. Drawing commands carry none of that.
  • The pieces belong together. One gradient across a whole figure, or a shape with holes in it, is a single painted surface rather than a stack of siblings.
  • The geometry is computed. Anything derived from data, where the shapes themselves depend on the input.

For a single shape in a layout, use a node instead. Nodes are the right tool when something needs flex layout, its own ref, or animation with .to().

How it works

Every method appends an operation and returns the same object, so a figure is one chain:

new Graphics()
  .rect({ width: 100, height: 100 })   // a shape
  .fill('red')                          // a paint

The list replays in order when the node draws it. Two things follow from that:

  • Order matters. A paint applies to the shapes recorded before it. A cut() uses the shape recorded immediately before it.
  • Nothing accumulates. A Graphics is a plain value, rebuilt each frame. Frame 10 looks the same whether you played to it or scrubbed back to it.

Drawing one

Override renderSelf on a node and hand the list to the render context:

import { Node, RenderContext, Graphics } from 'motion-script';

class Blob extends Node {
  protected renderSelf(ctx: RenderContext): void {
    ctx.draw(
      new Graphics()
        .ellipse({ width: 200, height: 200 })
        .fill('tomato'),
    );
  }
}

// <Blob width={400} height={400} />

Coordinates

Drawing commands are authored y up, with the origin at the node's own centre. Positive y is up the screen.

new Graphics()
  .rect({ x: 0, y: 100, width: 40, height: 40 })   // 100px above centre
  .rect({ x: 0, y: -100, width: 40, height: 40 }); // 100px below centre

This matches node x/y and rotation, so a drawn figure and a figure built from nodes agree about which way is up.

The methods

GroupMethodsWhat they do
Shapesrect ellipse path line polygon polygram text richTextDeclare geometry
Paintfill stroke shadowPaint the shapes recorded so far
Compositingcut mask applyMask endMaskPunch holes, or clip content to a drawn shape
Transformsrotation scale opacity effectsTurn, fade or filter the result

What Graphics does not do

  • No layout. Drawing commands use absolute coordinates in the node's local space. Flex, gap and padding belong to nodes.
  • No refs or .to(). You cannot animate a recorded operation. Animation comes from rebuilding the figure each frame from values that change. See Animating a drawing.