Shape

Responsibility

Shape is the atomic primitive for simple geometry. Its geometry lives in payload; its fill, stroke and marker semantics live in style. The supported shape kinds are rectangle, circle, ellipse, line, polyline and polygon.

Complete rectangle

The following is a complete layer-shaped record. parentLayerId, order, frame, transform and timing belong to the common layer contract; shape-specific fields are under payload and style.

{
  "id": "rounded-card",
  "type": "shape",
  "parentLayerId": null,
  "order": 0,
  "frame": { "width": 640, "height": 360 },
  "transform": {
    "translate": { "x": 320, "y": 240, "z": 0 },
    "rotate": { "x": 0, "y": 0, "z": 0 },
    "scale": { "x": 1, "y": 1, "z": 1 },
    "anchor": { "x": 320, "y": 180, "z": 0 },
    "skew": { "x": 0, "y": 0 }
  },
  "timing": { "start": 0, "duration": 5000 },
  "payload": {
    "shape": "rectangle",
    "cornerRadius": 28,
    "rx": 28,
    "ry": 28
  },
  "style": {
    "fill": "#102A43",
    "fillOpacity": 1,
    "stroke": "#2EE6C5",
    "strokeWidth": 4,
    "strokeOpacity": 0.9,
    "strokeJoin": "round",
    "strokeCap": "round",
    "vectorEffect": "none",
    "paintOrder": ["fill", "stroke"]
  }
}

Geometry kinds

KindGeometry fieldsNotes
rectanglecornerRadius, rx, ryrx/ry are optional rounded-corner radii
circleframe width and heightThe frame defines the primitive bounds
ellipseframe width and heightThe frame defines the horizontal and vertical radii
linestart, endRequires both points
polylinepointsAt least two points; remains open
polygonpointsAt least three points; closes the contour

Point coordinates are local to the shape frame. The layer transform moves the complete primitive; it does not rewrite the local points.

Line, polyline and polygon examples

[
  {
    "id": "divider",
    "type": "shape",
    "parentLayerId": null,
    "order": 1,
    "frame": { "width": 500, "height": 80 },
    "transform": {
      "translate": { "x": 40, "y": 80, "z": 0 },
      "rotate": { "x": 0, "y": 0, "z": 0 },
      "scale": { "x": 1, "y": 1, "z": 1 },
      "anchor": { "x": 0, "y": 0, "z": 0 },
      "skew": { "x": 0, "y": 0 }
    },
    "timing": { "start": 0, "duration": 5000 },
    "payload": {
      "shape": "line",
      "start": { "x": 0, "y": 40 },
      "end": { "x": 500, "y": 40 },
      "pathLength": 500
    },
    "style": {
      "stroke": "#FFFFFF",
      "strokeWidth": 4,
      "strokeCap": "round"
    }
  },
  {
    "id": "mountain",
    "type": "shape",
    "parentLayerId": null,
    "order": 2,
    "frame": { "width": 600, "height": 300 },
    "transform": {
      "translate": { "x": 0, "y": 0, "z": 0 },
      "rotate": { "x": 0, "y": 0, "z": 0 },
      "scale": { "x": 1, "y": 1, "z": 1 },
      "anchor": { "x": 0, "y": 0, "z": 0 },
      "skew": { "x": 0, "y": 0 }
    },
    "timing": { "start": 0, "duration": 5000 },
    "payload": {
      "shape": "polygon",
      "points": [
        { "x": 0, "y": 280 },
        { "x": 140, "y": 80 },
        { "x": 260, "y": 210 },
        { "x": 390, "y": 40 },
        { "x": 600, "y": 280 }
      ]
    },
    "style": {
      "fill": "#18B89A",
      "stroke": "#D8FFF7",
      "strokeWidth": 3,
      "strokeJoin": "round"
    }
  }
]

Paint and stroke

Fill and stroke are independent. A paint can be a color shorthand, none, a solid object, a linear/radial/conic gradient, a pattern or a named paint reference.

{
  "style": {
    "fill": {
      "type": "linear-gradient",
      "x1": 0,
      "y1": 0,
      "x2": 1,
      "y2": 1,
      "gradientUnits": "objectBoundingBox",
      "stops": [
        { "offset": 0, "color": "#2EE6C5" },
        { "offset": 1, "color": "#6257FF", "stopOpacity": 0.8 }
      ]
    },
    "stroke": "#FFFFFF",
    "strokeWidth": 6,
    "strokeOpacity": 0.75,
    "strokeDash": { "array": [12, 8], "offset": 0 }
  }
}
Style fieldMeaning
fill, fillOpacityInterior paint and alpha
stroke, strokeWidth, strokeOpacityOutline paint, width and alpha
strokeJoinmiter, bevel or round
strokeCapbutt, square or round
strokeMiterLimitLimit for sharp miter joins
strokeDashDash array and optional offset
paintOrderOrdering of fill, stroke and markers
vectorEffectnone or non-scaling-stroke

Rounded corners are geometry semantics, not a renderer resource. The cornerRadius, rx and ry fields are valid only for rectangles.