app-tour
app-tour
APP-TOUR primitives — how a promo POINTS AT one thing on a screen.
Read the rig's notes
Product tours are made of four tags and one rule.
ui the app itself, rasterised onto the device glass.
Cheap, sharp, and completely FLAT: its items are
pixels in a canvas, so nothing in here can be lifted
off, framed by the camera, or lit. Everything the
tour does NOT touch lives here.
ui3d(overlay=screen) the tour layer. Real plane meshes, surface-anchored
flush on that same glass in the SAME coordinate
space — an item authored at the same x/y sits
pixel-exact on its texture twin. Being real
geometry, it can leave the display (+z), be framed
by id, and cast into the scene's light.
mouse the pointer. Its move keyframes address UI items BY
ID — texture items included — so a click tracks its
button while the phone is still turning.
ui3d (free-standing) the callout. A panel that belongs to the SCENE
rather than to the screen, met by a leader line in
world millimetres.
THE RULE: author the thing TWICE. Once in the texture, where it is just part
of the app, and once in an overlay, where it is the subject. At rest the two
are one image; the overlay is the only thing that ever moves.
STACKING. `lift` is millimetres off the glass and doubles as the paint order
of the tour: base app 0 · scrim 0.02 · popped card 0.04 · hero control 0.06.
Give every overlay in a scene its own lift or they z-fight on the display.
SCREEN mm -> WORLD mm. A leader line, a world label or a floating panel has
to meet the popout in world space. For an UNROTATED device at (px, py, pz)
with a W x H glass, a screen point (sx, sy) is:
world = (px + sx - W/2, py + H/2 - sy, pz + glassZ + lift + dz)
Screen y runs DOWN and world y runs UP, hence the flip. The iphone glass
sits at z = +6.3 in the device's own frame. Rotate the device and this stops
being arithmetic — which is why scene 05 keeps its phone square-on.
FIVE TRAPS, every one of them found the hard way:
1. iphone safe-top pushes every TEXTURE item down ~4.6mm to clear the
Dynamic Island, and does NOT touch the overlays. A flush twin is then
4.6mm out of register. Author `safe-top=off` and your own top margin.
2. Overlay stage size. `width`/`height` on the overlay IS the glass in mm
(iphone 71x154, ipad 197x262, laptop 346x223, chrome 480x300). Leave it
off and every coordinate inside is read against 1920x1080 instead.
3. Cursor coordinate keyframes are RELATIVE to the mouse's authored
`position` — its home. `value="0 0 0"` means "at home"; repeating the
home coordinates in a kf puts the pointer at twice the distance. Only
`absolute=true` reads a value as a world point. (Camera keyframes are
the opposite: a camera is never rebased, so its values are absolute.)
4. Framing. A texture item has no world bounds, so `node=<texture item>`
never resolves. A device-mounted overlay IS real geometry and is the
documented way to frame a region of a screen — but its framed pose only
resolves in the FIRST scene of a reel today; seek into any later scene
and the solve reads the overlay's un-anchored stage coordinates and the
shot lands off the device. (camera-framing-devices scene 08 has the same
symptom.) Until that is fixed, frame the DEVICE or a FREE-STANDING ui3d
panel — both are ordinary scene nodes and both are exact. Keep the first
framed beat a couple of seconds in, and use `bounds=union side=front`.
5. `scroll` moves the TEXTURE's children only. An overlay does not ride it,
so pop the twin AFTER the scroll parks, at the row's settled y.
One app throughout — Flowlet, a light UI on a dark stage, so a scrim reads as
a scrim and a popout reads as a card in the air.
Scene map, one idea each:
01 LIFT a card leaves the glass, and the slot it left behind
02 SPOTLIGHT a scrim under the tour layer, one button above it
03 POINTER the cursor addresses a button by id, then the pop fires
04 FRAME the row hands off to a world panel, and the camera names it
05 CALLOUT a world panel and a leader line, met in world millimetres
06 STEPS a three-stop chain on one screen, one scrim throughout
07 SCROLL reach a row deep in a list, park, then pop its twin
08 DESKTOP the same four tags on a chrome window
09 ATLAS every layer at once, labelled with its lift
Capture: nx run tools:capture:webgl -- --project promos/primitives/app-tour/app-tour.promo
Preview: /packages/runtime/index.html?project=promos/primitives/app-tour/app-tour.promo- Topic
- uis
- Scenes
- 9
- Kind
- reference rig
//
APP-TOUR primitives — how a promo POINTS AT one thing on a screen.
Product tours are made of four tags and one rule.
ui the app itself, rasterised onto the device glass.
Cheap, sharp, and completely FLAT: its items are
pixels in a canvas, so nothing in here can be lifted
off, framed by the camera, or lit. Everything the
tour does NOT touch lives here.
ui3d(overlay=screen) the tour layer. Real plane meshes, surface-anchored
flush on that same glass in the SAME coordinate
space — an item authored at the same x/y sits
pixel-exact on its texture twin. Being real
geometry, it can leave the display (+z), be framed
by id, and cast into the scene's light.
mouse the pointer. Its move keyframes address UI items BY
ID — texture items included — so a click tracks its
button while the phone is still turning.
ui3d (free-standing) the callout. A panel that belongs to the SCENE
rather than to the screen, met by a leader line in
world millimetres.
THE RULE: author the thing TWICE. Once in the texture, where it is just part
of the app, and once in an overlay, where it is the subject. At rest the two
are one image; the overlay is the only thing that ever moves.
STACKING. `lift` is millimetres off the glass and doubles as the paint order
of the tour: base app 0 · scrim 0.02 · popped card 0.04 · hero control 0.06.
Give every overlay in a scene its own lift or they z-fight on the display.
SCREEN mm -> WORLD mm. A leader line, a world label or a floating panel has
to meet the popout in world space. For an UNROTATED device at (px, py, pz)
with a W x H glass, a screen point (sx, sy) is:
world = (px + sx - W/2, py + H/2 - sy, pz + glassZ + lift + dz)
Screen y runs DOWN and world y runs UP, hence the flip. The iphone glass
sits at z = +6.3 in the device's own frame. Rotate the device and this stops
being arithmetic — which is why scene 05 keeps its phone square-on.
FIVE TRAPS, every one of them found the hard way:
1. iphone safe-top pushes every TEXTURE item down ~4.6mm to clear the
Dynamic Island, and does NOT touch the overlays. A flush twin is then
4.6mm out of register. Author `safe-top=off` and your own top margin.
2. Overlay stage size. `width`/`height` on the overlay IS the glass in mm
(iphone 71x154, ipad 197x262, laptop 346x223, chrome 480x300). Leave it
off and every coordinate inside is read against 1920x1080 instead.
3. Cursor coordinate keyframes are RELATIVE to the mouse's authored
`position` — its home. `value="0 0 0"` means "at home"; repeating the
home coordinates in a kf puts the pointer at twice the distance. Only
`absolute=true` reads a value as a world point. (Camera keyframes are
the opposite: a camera is never rebased, so its values are absolute.)
4. Framing. A texture item has no world bounds, so `node=<texture item>`
never resolves. A device-mounted overlay IS real geometry and is the
documented way to frame a region of a screen — but its framed pose only
resolves in the FIRST scene of a reel today; seek into any later scene
and the solve reads the overlay's un-anchored stage coordinates and the
shot lands off the device. (camera-framing-devices scene 08 has the same
symptom.) Until that is fixed, frame the DEVICE or a FREE-STANDING ui3d
panel — both are ordinary scene nodes and both are exact. Keep the first
framed beat a couple of seconds in, and use `bounds=uni