trans() --- Waypoint Movement Cue
trans(...) moves an SVG element between waypoints — plain A-to-B
movement (and A→B→C→B→D… chains) with no visible path. Where
o2p() animates along a drawn path, trans() needs only
targets.
trans(uid:mover, to:[targetB], dur:2, trig:playhead)
The element's own authored position is the implicit starting point.
Waypoints — to:[…]
A list, mixing freely:
| Form | Meaning |
|---|---|
| element id | move so our centre lands on that element's centre |
[x, y] pair |
absolute centre position (authored score units) |
trans(to:[t-b1], dur:2) // A → B, stop at B
trans(to:[a, b, a, c], dur:1, hold:0.4) // chain, pausing at each arrival
trans(to:[[4700, 100], [4950, 300]], dur:1) // bare coordinates
Target elements are ordinary SVG objects with ids — draw them in Inkscape or with the + tool, and reference them by uid/id. Waypoints are resolved when the cue triggers, so targets that moved since load are honoured.
In the DSL editor the to field has a click score button: arm it and
each click on the score appends an [x, y] waypoint (Shift+click appends the
clicked element's id), with numbered markers showing the route.
Modes
| Mode | Behaviour |
|---|---|
once (default) |
travel the list, stay at the last waypoint |
loop |
after the last waypoint, glide back to the start and repeat |
alternate |
walk the list forwards then backwards, forever |
Timing and easing
dur:— seconds per leg. A number, or a pattern for varied tempo:dur:Prand(0.4, 0.8, 1.5, inf)hold:— pause (seconds) at each arrivalease:— any anime.js easing:linear,easeInOutQuad(default),easeOutElastic,easeOutBounce, …
dur:, ease: and hold: all take a list or a pattern, so a
multi-waypoint journey can change character per leg:
trans(to:[a, b, c], dur:[1, 0.25, 2])
trans(to:[a, b, c], dur:1, ease:[linear, easeOutBounce, easeInQuad])
trans(to:[a, b, c], dur:1, hold:[0.2, 1, 0.2])
trans(to:[a, b, c], dur:Prand(0.5, 1, inf), ease:Prand(linear, easeOutElastic, inf))
A list is indexed by waypoint — the leg into waypoint i uses the i-th
dur/easing, and the arrival at waypoint i the i-th hold, cycling if
the list is shorter than the journey (home legs/arrivals in
loop/alternate use the first entry). A Pseq/Prand pattern draws a
fresh value per leg instead.
Combining with other cues
Movement uses the CSS translate property, which composes independently
with transform — so trans() coexists with rotate() and scale() on
the same element:
trans(uid:m, to:[b], dur:4) rotate(uid:m-r, dur:1, trig:auto)
Triggering, visibility, observer
trig:autostarts immediately;trig:playheadwhen the playhead arrives;tdelay:delays after triggerinit:prestates work as for other animation cues- Offscreen pausing is journey-aware: a mover keeps running while any
part of its journey — its home position or any waypoint — is onscreen,
even when the mover itself has travelled out of view (like o2p keeps
running while its path is visible). Only a fully offscreen journey
pauses; opt out entirely with
observer:0(see rotate() — offscreen pausing)
Driving other cues
A trans() publishes what it is doing as it travels, so a moving bar can
drive a parameter the way a fader does — not just fire a cue it passes over:
| Channel | Meaning |
|---|---|
t |
progress through the whole waypoint list (0–1) |
legT |
progress along the current leg (0–1) |
x |
x across the travel (0–1) |
y |
y across the travel (0–1) |
x and y are normalised inside the box the element actually travels
through — home plus every waypoint — not in score units. A bar that only
moves horizontally therefore reports y as 0 throughout.
Bind any of them with follow():
trans(uid:mover, to:[tEnd], dur:5, mode:loop, trig:auto)
synth(uid:pad, wave:sine, freq: follow(mover.t, 90, 2000), amp:0.1)
The difference from trig:mover is the difference between a value and an
event. follow(mover.t, …) follows the bar the whole way across; trig:mover
fires once, when the bar passes over the thing it triggers. A score can use
both from the same mover.
Open the connections view to see
these as ports, and demo-connections for a worked example.
OSC output
osc:1 streams the mover's state over OSC — useful for driving sound or
external processes from the movement itself:
trans(uid:m1, to:[a, b, c], dur:2, osc:1)
Continuous stream on /trans/<uid> (throttled, ~30 ms):
| Arg | Meaning |
|---|---|
| 0 | progress through the whole waypoint list (0–1) |
| 1 | progress along the current leg (0–1) |
| 2 | centre x (score units) |
| 3 | centre y (score units) |
| 4 | index of the waypoint this leg is heading for (-1 = returning home) |
Arrival events, sent immediately (never throttled):
/trans/<uid>/waypoint [index] // -1 = arrived back at the home position
osc:<number>larger than 1 sets the stream throttle in ms (osc:100≈ 10 messages/s)oscaddr:overrides the addressosc:also exempts the cue from offscreen pausing — sound keeps following the movement even when the mover has scrolled out of view
Resetting
The ⏮ button in the top bar resets all animations to their authored start positions — movers return home, rotations and scales clear.
Rewind-to-zero does the same: jumping the transport back to the start
of the score resets every animation, on the host and on all synced
clients. Small rewinds and mid-score jumps deliberately don't — a
playhead-triggered trans() simply restarts from home when the playhead
crosses it again.
Examples
See the demo-trans project: A-to-B, waypoint chains, loop/alternate, three easing curves side by side, coordinate waypoints with random tempo, an OSC-streaming mover (open the OSC monitor while it plays), and a closing section on per-leg dur/ease/hold lists and patterns.
http://localhost:8001/?project=demo-trans
Tip: use ← → or ↑ ↓ to navigate the docs