scene

One of the two nodes a document holds directly, and the only one that renders where it is written. The body is the narrative — prose, headings, callouts — and the detail declares the canvas: the environments, and the block content shown beside them. A document is a sequence of scenes, read in order.

sceneNodeAliases:scn

#The scene

A scene is a body of narrative and a detail that declares the canvas. A document is a sequence of scenes, read in order. The scene's own attributes govern its animation timeline — duration (its implicit attribute, auto by default), autoplay, and loop.

scene{
    # A heading
    Narrative prose, read top to bottom.
}[
    canvas.graph{
        curve(expression: sin(x))
    }
]
Reference:scenestep

#Narrative and canvas

The body { } holds what is read: paragraphs, headings, lists, equations, callouts, dividers, references. The detail [ ] holds what is shown: canvas environments (canvas.graph, canvas.code) and supporting canvas content such as table and image.

Most of the content vocabulary is legal in both — prose, the four headings, lists and equations read the same in either slot. What is not: the four callouts (definition, note, example, task) and the internote reference are narrative only, and table, image, the controls, the cues and the canvas environments are detail only. Each construct's reference page carries its own Allowed in row.

A detail can be opened full screen, without its narrative beside it — so what is on the canvas has to hold as a picture on its own. Selecting canvas content covers what that asks of the marks.

#Steps

A step — written as === on its own line in the narrative — carves the scene's timeline into steps. Everything animated anchors to those steps: a cue's in: 2 fires at step two, a !cue.to's at: 2 starts its move there. The reader's progress through the text advances the canvas.

A marker is therefore a timeline trigger rather than a paragraph break — paragraphs separate with a blank line — so a scene whose detail never changes carries none at all, and a scene with markers has something anchored to each of them. Prose and canvas state gives the check.

scene{
    First the data alone.
    ===
    Then the fitted line.
}[
    canvas.graph{
        scatter#points(x: 1, 2, 3; y: 2.0, 2.4, 3.1)
        cue{
            fit(of: #points; model: polynomial; degree: 1)
        }(
            in: 1
        )
    }
]

#Environments and splits

A detail may declare two canvas environments; the scene's direction attribute arranges them — auto (the default), horizontal side by side, vertical stacked — and ratio gives the first environment's share over the second's, written as a fraction like 3/2.

auto follows the space the canvas has: stacked while the note is being read, where the canvas column is far taller than it is wide and two side-by-side halves of it are unreadable, and side by side in presentation, where the canvas has the whole screen and height is what is scarce. Leave it at auto unless the arrangement itself carries meaning.

scene{
    A graph beside its code.
}[
    canvas.graph#g{
        curve(expression: x^2)
    }
    canvas.code{
        lines{
            y = x ** 2
        }
    }(
        language: python
    )
](
    ratio: 3/2
)
Write horizontal or vertical only when the split has a semantic reason to hold the same axis everywhere — a number line reading under the graph it indexes is vertical in presentation too, and a before/after pair stays horizontal in the reading view. A fixed direction chosen for how it happened to look in one of the two is the case auto exists for.

#Continuing an environment

An environment carries an id on its node — canvas.graph#projectile{...} — and a later scene's environment can point back at it with continue: #projectile. What continues is the session state: the view they explored, the elements they added. continue: hands off state, never markup — the content is the new environment's own.

The scene's parameters do not continue, because they are not any environment's to hand over — see below.

#Parameters are the scene's

A parameter belongs to the scene rather than to an environment in it. A slider written inside one graph declares a quantity every environment in that scene reads — so a year picked on a map is the year the chart beside it shows, and there is one row for it in the scene's footer however many environments read it.

Which means a control need not be written inside an environment at all. It may sit in the scene's detail beside them, belonging to neither, which is the honest place for a quantity two environments share.

scene{
    Both halves are read at the same year.
}[
    slider:t(over: #pop.year; name: Year)

    canvas.geo:world{
        choropleth(regions: #pop.country; values: #pop.millions; slice: #pop.year)
    }
    canvas.graph{
        bar(x: #pop.country; y: #pop.millions; slice: #pop.year)
    }
]

Two controls naming the same parameter in one scene is an error naming both: the interaction chapter has what a control declares.

Ids share one document-wide namespace and resolve forwards and backwards — a continue: may point at an environment declared in any scene, and a collision between any two #ids anywhere is an error.

#Attributes

durationImplicit
How long one playback of a step lasts: what the play control fills over, and when Replay, or the next loop, comes. auto, the default, is as long as the step's cues take. A duration is never shorter than the cues — nothing is cut off — so what a longer one adds is a hold on the finished picture: duration: 4s on a 1.5s turn leaves the result on screen for another 2.5s before it goes round again.
Can be written as shorthand: scene:value
Defaultauto
autoplay
Whether the canvas animates as soon as the reader reaches it. On by default. !autoplay makes each step with an animation wait, still at its start, until the reader presses play in the canvas toolbar — for motion the reader should watch from the beginning rather than catch halfway. A step that animates nothing, or only fades something in briefly, has no play control and goes ahead regardless.
Defaulttrue
loop
Play each step's animation over and over: when a playback ends it starts again, until the reader pauses it. duration sets how long each time round lasts. With !autoplay it waits for the first press of play, then loops.
Defaultfalse
direction
Split arrangement when the detail declares two canvas environments: horizontal (side by side) or vertical (stacked).
horizontalvertical
Defaultauto
ratio
The first environment's share of a split over the second's, e.g. 3/2. Only meaningful with two canvas environments.

#Allowed content

#Examples

scene{
    # Title
    Intro paragraph.
}
scene{
    # With Detail
    Explain the concept.
}[
    canvas.code{
        lines{
            print("hello")
        }
    }(
        language: python
    )
]

Last updated