Diagram

canvas.diagramNode

A diagram environment on the scene's canvas: an uploaded image annotated with pins, a flowchart, a simple tree. Its image: names an uploaded asset by file name — canvas.diagram:cell.jpg is an annotated image with no child node needed — and a flowchart environment simply omits it. Boxes are arranged by the environment, layered along flow:, so a flowchart is written as what connects to what; pins carry their own coordinates. Positions here are fractions of the content frame with the origin at the TOP LEFT and y running DOWN — 0.62, 0.31 is 62% across, 31% from the top, the way a position is read off an image — unlike the graph's y-up mathematics. The frame is a camera: focus: (a point, or #id of a box or pin) and zoom: (a multiplier over the fitted frame) are both animatable with !cue.to, so one keyframe on each glides into a feature as the narrative reaches it.

Writing with it:Selecting canvas content

#The diagram environment

canvas.diagram holds the pictures that are neither plots nor maps: an uploaded image annotated with pins, a flowchart, a simple tree. Its implicit attribute is image, an uploaded asset named by its file name — canvas.diagram:cell.jpg is an annotated image with no child node needed — and a flowchart environment simply omits it.

Positions are fractions of the content frame with the origin at the top left and y running down: 0.62, 0.31 is 62% across and 31% from the top, the way a position is read off an image. This is deliberately not the graph's y-up mathematics — a free-form coordinate drawing belongs in canvas.graph with !show background.

#Images and pins

A pin is a labelled point on the image: a dot on the feature, a short hairline leader, the label beside it. at: is its implicit attribute; side: places the label, defaulting to whichever side has room. Cues gate pins exactly as they gate graph marks, so annotations arrive with the narrative.

canvas.diagram:cell-micrograph.jpg{
    pin#nucleus(at: 0.62, 0.31; label: Nucleus)

    cue{
        pin(at: 0.28, 0.55; label: Mitochondrion)
    }(
        in: 1
    )
}

#Boxes and arrows

A flowchart is written as what connects to what, never as coordinates. box declares the things and arrow the relations between them — endpoints are #ids of boxes or pins in the same environment — and the environment arranges the result in layers along flow:, down by default or right. A tree is the same arrangement with the arrows all pointing one way.

canvas.diagram{
    box#sample(label: Sample collected; shape: terminal)
    box#pcr(label: PCR amplify; sub: 30 cycles)
    box#check(label: Enough DNA?; shape: decision)

    arrow(from: #sample; to: #pcr)
    arrow(from: #pcr; to: #check)
    arrow(from: #check; to: #pcr; label: no; dashed)
}(
    flow: down
)
The arrangement is computed over the whole environment, cues included: a cue controls when a box is seen, never where it sits, so nothing shifts as steps fire. A hidden: box keeps its place for the same reason. cue.draw strokes an arrow in along its own length; a dashed: arrow fades instead, since a dash pattern and the draw reveal cannot share one stroke.

#Shapes

shape: carries the flowchart conventions a reader already knows: box (the default rounded rectangle), decision (the diamond), terminal (the pill) and ellipse. A box's label: is rich inline — maths, bold and !value all work — and sub: sets a second, smaller muted line beneath it.

#Placing a box by hand

A box with at: sits out of the arrangement at that fraction of the frame — a legend beside a flowchart, a caption box on an image. Everything else still arranges around it.

#focus, zoom and the glide

The frame is a camera. focus: takes a fractional point or #id naming a box or pin the environment already draws, and zoom: multiplies over the fitted frame — omitted, the content fits the environment. Both are animatable, so one !cue.to on each glides into a feature as the narrative reaches it; interactive additionally hands the reader wheel-zoom and drag, with a double-click back to the authored frame.

canvas.diagram:cell-micrograph.jpg{
    pin#nucleus(at: 0.62, 0.31; label: Nucleus)
}(
    focus: 0.5, 0.5 !cue.to{#nucleus}(at: 1; over: 800ms)
    zoom: 1 !cue.to{3}(at: 1; over: 800ms)
)

#Attributes

imageImplicit
string
Also written: src, sourceThe uploaded image the environment draws under its pins, named by its file name exactly as the block image names one. Normally written in the head, canvas.diagram:cell.jpg. Omitted, the environment's frame is the arranged extent of its boxes.Can be written as shorthand: canvas.diagram:value
flow
Which way the arrangement runs: down stacks layers top to bottom, right runs them left to right. Trees and flowcharts are the same arrangement read in different directions.
Defaultdown
title
string
The caption set over the top-left of the environment, on the pane's own ground.
Where the camera looks: a fractional point, or #id naming a box or pin this environment already draws — so a frame aimed at a feature it also labels states that feature once. Animatable with !cue.to; absent, the frame centres.
A multiplier over the fitted frame, animatable with !cue.to. NO default: an omitted zoom is auto — the content fits the environment — and zoom: 1 written out means exactly the fit.
interactive
boolean
Reader exploration: wheel-zoom about the cursor, drag to pan, double-click to reset. The explored camera overrides the authored or keyframed one once touched.
Defaultfalse
continue
Inherit an earlier diagram environment's state: continue: #that-environment. The reader's explored camera carries forward; every authored attribute is the new environment's own.

#Allowed content

#Allowed in

#Examples

canvas.diagram:cell-micrograph.jpg{
    pin#nucleus(at: 0.62, 0.31; label: Nucleus)
    pin(at: 0.28, 0.55; label: Mitochondrion)
}(
    focus: 0.5, 0.5 !cue.to{#nucleus}(at: 1; over: 800ms)
    zoom: 1 !cue.to{3}(at: 1; over: 800ms)
)
canvas.diagram{
    box#sample(label: Sample collected; shape: terminal)
    box#pcr(label: PCR amplify; sub: 30 cycles)
    box#check(label: Enough DNA?; shape: decision)
    arrow(from: #sample; to: #pcr)
    arrow(from: #pcr; to: #check)
    arrow(from: #check; to: #pcr; label: no)
}(
    flow: down
)