You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
3.5 KiB
85 lines
3.5 KiB
|
4 months ago
|
# motion — animation runtime
|
||
|
|
|
||
|
|
`EngineMotion` is the runtime engine for the UIX motion system: it registers
|
||
|
|
motion **presets** and **runs** them. It is an art (a pure runtime artifact,
|
||
|
|
public methods over private state, no reactive `$state`) so that **both** UIX
|
||
|
|
layers can consume it via `uix.motion` without a cross-layer dependency:
|
||
|
|
|
||
|
|
- **soma** (`Presence`) calls `motion.run(node, phase)` to run + await a JS
|
||
|
|
preset (a `spring`) before unmounting — the gating soma can't get from
|
||
|
|
`getAnimations()` alone.
|
||
|
|
- **eidos** generates the CSS (keyframes + preset rules), registers its visual
|
||
|
|
presets into the engine, and drives wrappers.
|
||
|
|
|
||
|
|
The engine owns the **execution**; eidos owns the **CSS generation** and the
|
||
|
|
visual presets **data**. Neither imports the other — they meet at `uix.motion`.
|
||
|
|
|
||
|
|
## The two moments
|
||
|
|
|
||
|
|
Motion occurs in two moments, each animable (one, the other, or both):
|
||
|
|
|
||
|
|
| | `--event` | `--state` |
|
||
|
|
|---|---|---|
|
||
|
|
| Attr | `data-event-*` (sema) | `data-state` (soma) |
|
||
|
|
| What | the perceptual **firma** during a signal's hold | the transition to/from a persistent condition |
|
||
|
|
| Registry | `signatures` (eidos generates CSS) | `presets` (named, per-component) |
|
||
|
|
|
||
|
|
`EngineMotion` runs the **`--state`** presets (CSS → settled; JS → driver). The
|
||
|
|
`--event` firma is CSS that eidos generates from `signatures`; the engine does
|
||
|
|
not run it.
|
||
|
|
|
||
|
|
## API
|
||
|
|
|
||
|
|
```ts
|
||
|
|
const motion = createEngineMotion({ dom }) // dom: a MotionDom port
|
||
|
|
|
||
|
|
motion.register('scale-fade', { driver: 'css', … }) // eidos registers presets
|
||
|
|
motion.register('pop', { driver: 'spring', enter: spring({ … }) })
|
||
|
|
|
||
|
|
motion.run(node, 'enter') // resolve node's data-animation-style + run
|
||
|
|
motion.enter(el, 'pop') // run a preset by name
|
||
|
|
motion.cancel(el) // cancel active JS motion on el
|
||
|
|
await motion.pending(el) // combined finished, for Presence
|
||
|
|
motion.dispose() // idempotent: cancel all + clear registry
|
||
|
|
```
|
||
|
|
|
||
|
|
- **CSS preset** → declarative: a settled handle (the generated CSS + soma's
|
||
|
|
`Presence` via `getAnimations()` do the work).
|
||
|
|
- **JS preset** → runs its `MotionRun` driver, normalises the result
|
||
|
|
(`Animation` | `Animation[]` | `MotionHandle`) to one handle, tracks it per
|
||
|
|
element. `pending(el)` is what Presence awaits for drivers (`spring`) that
|
||
|
|
`getAnimations()` can't see.
|
||
|
|
|
||
|
|
## Drivers (`./drivers`)
|
||
|
|
|
||
|
|
`MotionRun` factories for JS presets:
|
||
|
|
|
||
|
|
- **`spring`** — self-contained physics: an independent semi-implicit-Euler
|
||
|
|
spring per property, stepped via `ctx.dom.requestFrame`. Overshoot + settle —
|
||
|
|
the curve no cubic-bezier expresses. Cancellable via `ctx.signal`.
|
||
|
|
- **`waapi`** — `el.animate(...)`. The `Animation` is in `getAnimations()`, so
|
||
|
|
Presence awaits it for free.
|
||
|
|
- **`rect`** — FLIP: measures first/last rects, animates the inverse delta via
|
||
|
|
WAAPI (layout / shared-element transitions).
|
||
|
|
|
||
|
|
## The DOM port
|
||
|
|
|
||
|
|
This art imports no other art. The DOM dependency arrives **injected** and is
|
||
|
|
typed by the structural `MotionDom` port (`requestFrame` / `cancelFrame` /
|
||
|
|
`prefersReducedMotion`); the real `ActiveDom` satisfies it.
|
||
|
|
|
||
|
|
## Composition
|
||
|
|
|
||
|
|
```ts
|
||
|
|
// active-app (attach path)
|
||
|
|
const App = createActiveApp({
|
||
|
|
services: { dom: defineActiveDom(), motion: defineEngineMotion() }
|
||
|
|
});
|
||
|
|
|
||
|
|
// active-uix (standalone) creates it directly and exposes uix.motion.
|
||
|
|
```
|
||
|
|
|
||
|
|
Without a `dom` service the engine degrades (JS drivers settle; CSS is
|
||
|
|
declarative regardless). `duration` / `ease` are `string` (token keys or raw
|
||
|
|
values); eidos validates the keys — this art stays token-agnostic.
|