Diagram - Movement Lab
Explore a seated leg and foot, inspect geometric angles and compare a pinned frame.
#Scrub and compare a pose
Two original synthetic recordings each contain sixteen keyframes over 4.5 seconds: a seated knee extension and an ankle sweep. An original side-profile leg and foot rest beside a simple seat and platform. Choose a recording, scrub its frame strip and inspect the knee or ankle. These are drawing coordinates; none of the coordinates or angles is a patient measurement or a clinical target.
- In Seated knee extension, the first frame's knee angle is 90°. Pin reference, then scrub to the last frame. Its geometric knee angle becomes 170°; the dashed contour retains the first pose and the comparison reads +80°.
- Choose Knee or Ankle from Inspect joint, or select its marker in the drawing. The named choice and marker inspect the same coordinate vectors.
- Play runs to the final frame and stops. Pause holds the current interpolated pose; Step pauses and advances to the next whole keyframe. Replay starts again. The surrounding controls remain above the study.
- Choose Ankle sweep. The thigh, knee and ankle position remain fixed while the foot rotates. Its angle is 102° at frame 0, 64° at frame 8 and 102° at frame 15. These synthetic values are examples, not a recommended motion range. Recording changes restore the first frame, select the relevant joint and clear the incompatible reference.
- Pan or zoom with the floating controls. The reference retains the same contour and world transform. Fit restores the fixed complete movement envelope. Reset returns to the first frame, clears the reference and fits.
#Host coordinates and controlled geometry
The host owns original synthetic directions, sampled coordinates, frame position,
recording, reference and playback. pose.ts defines sixteen authored keyframe
directions for each recording and linearly interpolates joint coordinates between
adjacent frames. Coordinates are unitless drawing units. Interpolation is not a
physiological model and does not enforce constant limb length between keyframes.
The thigh, calf and foot are three genuine Diagram nodes with stable IDs. Original flat contours distinguish the thigh, tapered calf, heel, instep and toe. Their local joint-axis endpoints project exactly through public bounds and center rotation to the synthetic joint coordinates. Seat and platform are fixed Diagram context nodes; two joint-marker nodes provide inspection. Each segment's bounds include padding around its joint axis, keeping the complete heel, toe and curve control hull inside ordinary Diagram content clipping. Live and reference paths use the same local padding; no private clipping override is required. Nodes are flat in one world, with no additional rotated parent. The fixed framing node covers the complete motion envelope, so scrubbing preserves manual navigation rather than refitting each pose. Body geometry is in a locked layer; all edit constraints and editing shortcuts are disabled. Joint markers and named selection remain interactive.
A controlled public Store accepts each newer host pose with
store.synchronize(model, revision, transactionId). This is presentation
synchronization, not a saved clinical edit. It creates no per-frame Undo entry;
controlled synchronization clears history, and this example never offers editing
or history controls. Surviving public Session selection/focus stays stable through
frame updates. Changing recording intentionally selects its relevant knee/ankle.
Host revisions and synchronization IDs increase within the mounted lifetime.
#Angles and reference projection
Angles are the unsigned 0–180° angles between two vectors at the selected joint, calculated with a clamped dot product. Knee uses hip/knee/ankle; ankle uses knee/ankle/toe. Degenerate or nonfinite vectors return Unavailable rather than a fabricated angle. No joint limit, normative threshold, recovery rating or treatment interpretation is applied.
Pinning stores the current frame number for the current recording. The reference
angle uses that frame's coordinates; change is current minus reference in degrees.
The dashed reference uses the exact same authored segment contours, projected with public createDiagramScene,
using the same local bounds and world transform matrices as the live nodes. It
is projected content inside Diagram.Viewport, so the normal world transform
keeps it aligned during pan/zoom. It is noninteractive host artwork, never an
alternate rendering canvas or a private DOM geometry adapter.
#Finite playback and lifecycle
MotionPlayback is a bounded host clock with an injected scheduler. Normal playback
uses requestAnimationFrame and elapsed time, interpolating the sixteen keyframes
at 300ms spacing. The end is exact and finite. Pause cancels the scheduled callback;
seek, Step, Reset, recording changes and reference pinning pause first. A generation
token fences stale callbacks, and disposal also rejects later seek/play requests.
The page's visibility listener pauses when the model becomes hidden. Destroy removes that listener and the reduced-motion listener, cancels playback and disposes the Store; Diagram owns its Session and viewport observers. Reduced motion steps whole keyframes on the same finite clock with the same positions, angles, reference and endpoints. Scrubbing remains static and keyboard operable. Changing that preference pauses before adopting it; there is no autoplay or CSS pose transition.
#Copy and customize
Copy MovementLabDemo.vue with its _shared/movement-lab files: pose.ts, playback.ts, MotionJoint.vue, MotionInspection.vue, MotionFraming.vue, MotionIcon.vue and styles.css. Keep their relative paths together. The small provider children read the current Diagram state through useDiagramContext(). PrimeVue Button, Select and Slider provide the controls, and individual PrimeIcons Vue imports provide icons. Load the normal Diagram and PrimeVue theme styles. Local geometry and colors inherit the active primary, surface and light/dark scheme; no raster, icon font or external motion asset is needed. Change authored directions, lengths and joint vectors in pose.ts, keeping the framing envelope large enough for all recordings and references.
PrimeVue Slider scrubs whole keyframes from 0 to 15 with pointer input or arrows/Home/End. During playback, its handle and the adjacent pose frame/time readout follow the exact fractional pose. Public input pass-through attributes connect the visible label and readout without a private DOM adapter. Open named PrimeVue choices and use arrows/Home/End, Enter to select or Escape to dismiss. Buttons provide keyboard Play/Pause/Step, pin/clear, Reset and navigation. Joint markers have the same named choice without adding two small canvas buttons to the tab sequence. Frame/time, names, angle numbers, dashed outlines and polite action feedback convey state alongside color. The seated study remains readable in narrow view through full-envelope fit.
This local sample uses no real patient data, diagnosis, clinical scoring, treatment advice, backend, persistence, motion-capture device or physiological simulation. Physical touch, portable custom-content export fidelity and actual native hidden-model behavior require separate environment-specific verification.
See controlled state, navigation, content and architecture for public contracts. For navigation with more nodes, try the 1,000-node graph; rich-view caps limit mounted components without reducing the saved graph.