draw()
Put a shape on the map — a spell zone, a blast template, a wall.
Part of the Action API · Function reference
Signature
draw(args: DrawArgs): Promise<string>
Asynchronous. Resolves with the id of the shape it created.
draw is not always defined. It exists only when the action runs against a
map that can accept drawings. Check before calling:
if (typeof draw === 'function') {
await draw({ area, text: 'Wall of Fire' });
}
Parameters
draw() takes a single options object. Give it either an area or a shape.
Drawing a targeted area
| Field | Type | Description |
|---|---|---|
area |
TargetedArea | null |
The area the player placed with the targeting reticle, available in scope as area. Supplies shape, position, and size. |
When area is present, shape, origin, and size are ignored — the
drawing is exactly the region the player aimed at, which is the point. Circle,
rectangle, cone, and line areas can be drawn; a wall or path area throws.
Drawing a shape yourself
| Field | Type | Default | Description |
|---|---|---|---|
shape |
'circle' | 'square' | 'rectangle' | 'cone' | 'line' | 'wall' |
— | Required when there is no area. |
origin |
{ x?, y? } |
{ x: 0, y: 0 } |
Offset from the token's position. |
size |
number |
100 |
Radius for circle and cone; side length for square; both dimensions for rectangle. |
width |
number |
size |
Rectangle width. |
height |
number |
size |
Rectangle height. |
angle |
number |
0 |
Cone facing in degrees. 0 points right, 90 points down. |
arcAngle |
number |
60 |
Cone arc width in degrees. |
points |
Array<{x, y}> |
— | Required for line and wall; at least two vertices, each an offset from the token plus origin. |
Walls
Only meaningful with shape: 'wall', which is stored as a vision-blocking shape
rather than a drawing.
| Field | Type | Default | Description |
|---|---|---|---|
blockingMode |
'both' | 'vision' | 'movement' |
'both' |
What the wall stops. |
blocksVision |
boolean |
true |
false gives concealment rather than a hard block. |
wallHeight |
number |
none | Height in feet, used by shadow casting. |
Lifetime, labels, and style
| Field | Type | Default | Description |
|---|---|---|---|
duration |
number |
0 |
Rounds to persist. 0 or omitted is permanent. |
text |
string | null |
null |
A label drawn on the shape. |
metadata |
string |
null |
Tooltip text shown when someone hovers the shape. |
baseColor |
string | null |
null |
One colour to derive the whole palette from — see Colour. |
fillColor |
string | null |
#ff00004d |
Explicit fill. Overrides baseColor. |
strokeColor |
string | null |
#ff0000 |
Explicit outline. Overrides baseColor. |
strokeWidth |
number |
2 |
Outline thickness in pixels. |
opacity |
number |
1 |
Opacity of the whole shape. |
Returns
Promise<string> — the id of the created drawing or wall. Keep it if you want
to remove the shape later through another mechanism; draw() itself has no
delete counterpart.
Colour
Pass baseColor and the house style is derived from it: the fill is that colour
at 40% opacity, the outline is the same hue halfway to black at 20px, and any
text label matches the outline. That is how a module tints a zone by school or
category and still gets a consistent look.
await draw({ area, baseColor: '#c92a2a', text: 'Fireball' });
Colours must be hex. The map's renderer reads #RGB, #RRGGBB, and
#RRGGBBAA — and only those. An rgba(255, 0, 0, 0.3) fill renders fully
opaque, hiding the tokens standing in the zone. Write the alpha as the last
two hex digits instead: #ff00004d.
Expiry
With duration set, the shape is removed once the initiative round counter
reaches the current round plus duration. Rounds, not turns, and it needs
initiative to actually be running — outside
combat the counter never advances and the shape stays.
Examples
Leave a zone where the player aimed
if (area && typeof draw === 'function') {
await draw({
area,
baseColor: '#e8590c',
text: 'Wall of Fire',
metadata: '2d6 fire damage on entry',
duration: 10,
});
}
A burst centred on the caster
await draw({
shape: 'circle',
size: 300,
baseColor: '#1971c2',
text: 'Aura of Cold',
duration: 3,
});
A cone
await draw({ shape: 'cone', size: 350, angle: 90, arcAngle: 60, baseColor: '#2f9e44' });
A temporary barricade
await draw({
shape: 'wall',
points: [{ x: -150, y: 0 }, { x: 150, y: 0 }],
blockingMode: 'both',
duration: 5,
});
Errors
draw() throws — which surfaces as a red error in chat — when:
- neither
shapenorareais given shapeis not one of the six supported valuesshape: 'line'or'wall'is given fewer than twopointsshape: 'wall'is used where the host cannot create vision-blocking shapesarea.typeis'wall'or'path', neither of which can become a drawing
Notes and gotchas
- Known issue: manual placement is off.
originandpointsare added to the token's stored grid coordinates but drawn in pixels, so a shape positioned this way lands near the map's top-left corner rather than on the token.draw({ area })converts correctly and is the reliable path today. draw()really draws in the Test panel. Only chat is captured there; the shape is created on the map for everyone.metadatais hover-only. A zone nobody can identify without mousing over it is a coloured blob during someone else's turn — usetextfor anything that matters at a glance.awaitit if you need the id or want later steps to run after the shape exists.
See also
- Drawings, fog, and lighting
- Initiative and combat — what
durationcounts - Action API overview — including the
areavalue