PathAnimationLib — Path Animation Library
Animates a control along a path defined using SVG-like path syntax. Perfect for complex motion — curves, orbits, figure-8 patterns, bouncing trajectories, and wave paths. The control follows the path as a trajectory, and can optionally rotate to face its direction of travel. 43 functions.
| Category | Count | Description |
|---|---|---|
| Error Handling | 4 | pathani_error, errormsg$, strerror$, clearerror |
| Creation & Destruction | 3 | pathani# (2 overloads), pathani_free |
| Playback Control | 3 | start, stop, stopatcurrent |
| Path Data & Rotation | 5 | path# (set), path$ (get), clearpath#, rotate (get/set) |
| Timing | 4 | duration, delay (get/set) |
| Behavior — Easing | 4 | animationtype, interpolation (get/set) |
| Behavior — Flags | 8 | autoreverse, inverse, loop, enabled (get/set) |
| State Queries | 3 | running, normalizedtime, name$ |
| Triggers | 4 | trigger, triggerinverse (get/set) |
| Events | 5 | onfinish, onprocess (get/set), clearcallbacks# |
Cross-Platform Support
| Platform | Status | Notes |
|---|---|---|
| Windows | ✅ Full Support | Win32/Win64 |
| Linux | ✅ Full Support | GTK-based |
| Android | ✅ Full Support | Hardware-accelerated |
Error Handling
| Function | Signature | Description |
|---|---|---|
pathani_error() | pathani_error@ | Last error code (0 = no error) |
pathani_errormsg$() | pathani_errormsg$@ | Last error message as string |
pathani_strerror$(code) | pathani_strerror$@n | Description for a given error code |
pathani_clearerror() | pathani_clearerror@ | Clear the error state |
Error Codes
| Code | Constant | Description |
|---|---|---|
| 0 | ERR_NONE | No error |
| 1 | ERR_NIL_ANIMATION | Animation pointer is nil |
| 2 | ERR_INVALID_PATH | Invalid path data string |
| 3 | ERR_INVALID_VALUE | Invalid parameter value |
| 4 | ERR_ANIMATION_RUNNING | Cannot modify while animation is running |
How It Works
A path animation moves a control along a trajectory described by an SVG path string. The control’s position is interpolated along the path from start to end over the given duration. You define the trajectory with standard SVG path commands — lines, curves, arcs — and the animation engine handles the rest:
' 1. Create the animation on a control let ani# = pathani#(myCircle#) ' 2. Define the path (SVG syntax) pathani_path#(ani#, "M 50,200 C 150,50 350,350 450,200") ' 3. Optionally rotate to follow the path pathani_rotate#(ani#, 1) ' 4. Set timing pathani_duration#(ani#, 3.0) ' 5. Start! pathani_start(ani#)
pathani_rotate#(ani#, 1) to make the control face its direction of travel (great for arrows, vehicles, or directional objects).SVG Path Commands
Path data uses standard SVG path syntax. Uppercase commands use absolute coordinates; lowercase commands use relative offsets from the current position.
Movement & Lines
| Command | Parameters | Description |
|---|---|---|
M / m | x, y | Move to position (absolute / relative) |
L / l | x, y | Line to position (absolute / relative) |
H / h | x | Horizontal line to X (absolute / relative) |
V / v | y | Vertical line to Y (absolute / relative) |
Z / z | — | Close path (line back to start point) |
Cubic Bézier Curves
| Command | Parameters | Description |
|---|---|---|
C / c | x1,y1 x2,y2 x,y | Cubic Bézier with two control points |
S / s | x2,y2 x,y | Smooth cubic — mirrors previous control point |
Quadratic Bézier Curves
| Command | Parameters | Description |
|---|---|---|
Q / q | x1,y1 x,y | Quadratic Bézier with one control point |
T / t | x,y | Smooth quadratic — mirrors previous control point |
Arcs
| Command | Parameters | Description |
|---|---|---|
A / a | rx,ry rot large,sweep x,y | Elliptical arc to endpoint |
' Straight horizontal line "M 0,100 L 400,100" ' Square loop "M 50,50 L 350,50 L 350,350 L 50,350 Z" ' S-curve (cubic Bézier) "M 50,200 C 150,50 200,350 300,200 S 400,50 450,200" ' Full circle (two arcs) "M 50,175 A 150,150 0 1,1 350,175 A 150,150 0 1,1 50,175" ' Bouncing trajectory (quadratic) "M 25,300 Q 100,50 175,300 Q 250,100 325,300 Q 400,150 425,300"
Interpolation & Easing
Interpolation and easing control how fast the control moves along the path, not the shape of the path itself. The path geometry is fixed; the easing changes the speed profile:
Interpolation Curves
| Interpolation | Character | Best For |
|---|---|---|
"Linear" | Constant speed along path | Orbits, continuous loops, steady motion |
"Quadratic" | Gentle acceleration | Smooth starts |
"Cubic" | Moderate curve | Natural-feeling traversal |
"Sinusoidal" | Sine-wave speed | Oscillating speed along path |
"Elastic" | Springy speed | Playful, bouncy traversal |
"Bounce" | Bouncing speed | Stop-and-go at end of path |
Easing Types (AnimationType)
| Type | Effect | Description |
|---|---|---|
"In" | Slow start → fast end | Object accelerates along path |
"Out" | Fast start → slow end | Object decelerates along path |
"InOut" | Slow → fast → slow | Accelerate then decelerate |
"Linear" for most path animations. It gives constant speed along the path, which feels natural for orbits, figure-8s, and looping motion. Other curves change the speed while the trajectory remains the same.Creation & Destruction
| Function | Signature | Description |
|---|---|---|
pathani#(parent#) | pathani#@# | Create animation attached to parent control |
pathani#(parent#, name$) | pathani#@#$ | Create named animation attached to parent |
pathani_free(ani#) | pathani_free@# | Destroy animation object |
Playback Control
| Function | Signature | Description |
|---|---|---|
pathani_start(ani#) | pathani_start@# | Start the animation |
pathani_stop(ani#) | pathani_stop@# | Stop and reset to path start |
pathani_stopatcurrent(ani#) | pathani_stopatcurrent@# | Stop at current position on path |
Path Data & Rotation
Path Data
| Function | Signature | Description |
|---|---|---|
pathani_path#(ani#, pathdata$) | pathani_path#@#$ | Set SVG path data string |
pathani_path$(ani#) | pathani_path$@# | Get path data string |
pathani_clearpath#(ani#) | pathani_clearpath#@# | Clear path data |
Rotation
| Function | Signature | Description |
|---|---|---|
pathani_rotate#(ani#, flag) | pathani_rotate#@#n | If 1, control rotates to follow path tangent |
pathani_rotate(ani#) | pathani_rotate@# | Get rotate flag |
rotate = 1, the control automatically rotates to face the direction it is traveling along the path. This is ideal for arrow shapes, vehicles, fish, birds, or any object that should “point forward” along its trajectory.Timing
| Function | Signature | Description |
|---|---|---|
pathani_duration#(ani#, seconds) | pathani_duration#@#n | Set duration in seconds |
pathani_duration(ani#) | pathani_duration@# | Get duration |
pathani_delay#(ani#, seconds) | pathani_delay#@#n | Set delay before animation starts |
pathani_delay(ani#) | pathani_delay@# | Get delay |
Behavior Flags
Easing & Interpolation
| Function | Signature | Description |
|---|---|---|
pathani_animationtype#(ani#, type$) | pathani_animationtype#@#$ | Set easing: "In", "Out", "InOut" |
pathani_animationtype$(ani#) | pathani_animationtype$@# | Get easing type |
pathani_interpolation#(ani#, type$) | pathani_interpolation#@#$ | Set interpolation curve |
pathani_interpolation$(ani#) | pathani_interpolation$@# | Get interpolation type |
Boolean Flags
| Function | Signature | Description |
|---|---|---|
pathani_autoreverse#(ani#, flag) | pathani_autoreverse#@#n | If 1, plays forward then backward along path |
pathani_autoreverse(ani#) | pathani_autoreverse@# | Get autoreverse flag |
pathani_inverse#(ani#, flag) | pathani_inverse#@#n | If 1, traverses path in reverse |
pathani_inverse(ani#) | pathani_inverse@# | Get inverse flag |
pathani_loop#(ani#, flag) | pathani_loop#@#n | If 1, loops indefinitely |
pathani_loop(ani#) | pathani_loop@# | Get loop flag |
pathani_enabled#(ani#, flag) | pathani_enabled#@#n | Enable or disable the animation |
pathani_enabled(ani#) | pathani_enabled@# | Get enabled state |
State Queries
| Function | Signature | Description |
|---|---|---|
pathani_running(ani#) | pathani_running@# | Returns 1 if currently animating |
pathani_normalizedtime(ani#) | pathani_normalizedtime@# | Returns progress from 0.0 to 1.0 |
pathani_name$(ani#) | pathani_name$@# | Get the animation’s name |
Triggers
| Function | Signature | Description |
|---|---|---|
pathani_trigger#(ani#, expr$) | pathani_trigger#@#$ | Set trigger expression (starts animation) |
pathani_trigger$(ani#) | pathani_trigger$@# | Get trigger expression |
pathani_triggerinverse#(ani#, expr$) | pathani_triggerinverse#@#$ | Set inverse trigger (reverses animation) |
pathani_triggerinverse$(ani#) | pathani_triggerinverse$@# | Get inverse trigger expression |
Events
| Event Setter | Getter | Callback Signature | Description |
|---|---|---|---|
pathani_onfinish#(ani#, func$) | pathani_onfinish$(ani#) | function name(sender#) | Fired when animation completes |
pathani_onprocess#(ani#, func$) | pathani_onprocess$(ani#) | function name(sender#) | Fired on every animation frame |
pathani_clearcallbacks#(ani#) | — | — | Disconnect all callbacks |
Complete Examples
Straight Line
let frm# = form#("Line Path Demo", 400, 300) form_position#(frm#, 4) let ball# = circle#(frm#, 0, 125, 50, 50) circle_fill#(ball#, "#e74c3c") let pathAni# = pathani#(ball#) pathani_path#(pathAni#, "M 0,125 L 350,125") pathani_duration#(pathAni#, 2.0) pathani_interpolation#(pathAni#, "Sinusoidal") pathani_animationtype#(pathAni#, "InOut") pathani_autoreverse#(pathAni#, 1) pathani_loop#(pathAni#, 1) pathani_start(pathAni#) form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
Square Loop
let frm# = form#("Square Path Demo", 400, 400) form_position#(frm#, 4) let ball# = circle#(frm#, 50, 50, 40, 40) circle_fill#(ball#, "#3498db") let pathAni# = pathani#(ball#) pathani_path#(pathAni#, "M 50,50 L 310,50 L 310,310 L 50,310 Z") pathani_duration#(pathAni#, 4.0) pathani_interpolation#(pathAni#, "Linear") pathani_loop#(pathAni#, 1) pathani_start(pathAni#) form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
Circular Orbit
let frm# = form#("Orbit Demo", 400, 400) form_position#(frm#, 4) ' Center marker let center# = circle#(frm#, 190, 190, 20, 20) circle_fill#(center#, "Gray") ' Orbiting planet let planet# = circle#(frm#, 50, 175, 50, 50) circle_fill#(planet#, "#e67e22") ' Full circle using two arc commands let pathAni# = pathani#(planet#) pathani_path#(pathAni#, "M 50,175 A 150,150 0 1,1 350,175 A 150,150 0 1,1 50,175") pathani_duration#(pathAni#, 3.0) pathani_interpolation#(pathAni#, "Linear") pathani_loop#(pathAni#, 1) pathani_start(pathAni#) form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
S-Curve with Rotation
let frm# = form#("Curve Path Demo", 500, 400) form_position#(frm#, 4) ' Arrow shape that will rotate to follow the path let arrow# = path#(frm#) path_data#(arrow#, "M 0,-15 L 30,0 L 0,15 Z") path_fill#(arrow#, "#2ecc71") path_move#(arrow#, 50, 200) ' S-curve with rotation enabled let pathAni# = pathani#(arrow#) pathani_path#(pathAni#, "M 50,200 C 150,50 200,350 300,200 S 400,50 450,200") pathani_duration#(pathAni#, 4.0) pathani_rotate#(pathAni#, 1) pathani_interpolation#(pathAni#, "Linear") pathani_loop#(pathAni#, 1) pathani_start(pathAni#) form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
Figure-8
let frm# = form#("Figure-8 Demo", 500, 400) form_position#(frm#, 4) let ball# = circle#(frm#, 50, 175, 50, 50) circle_fill#(ball#, "#9b59b6") ' Figure-8 using cubic Bézier curves let p$ = "M 50,175 C 50,50 200,50 250,175 " p$ = p$ + "C 300,300 450,300 450,175 " p$ = p$ + "C 450,50 300,50 250,175 " p$ = p$ + "C 200,300 50,300 50,175" let pathAni# = pathani#(ball#) pathani_path#(pathAni#, p$) pathani_duration#(pathAni#, 5.0) pathani_interpolation#(pathAni#, "Linear") pathani_loop#(pathAni#, 1) pathani_start(pathAni#) form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
Bouncing Ball Trajectory
let frm# = form#("Bounce Path Demo", 500, 400) form_position#(frm#, 4) let ball# = circle#(frm#, 25, 300, 50, 50) circle_fill#(ball#, "#e74c3c") ' Bouncing arcs using quadratic Bézier let pathAni# = pathani#(ball#) pathani_path#(pathAni#, "M 25,300 Q 100,50 175,300 Q 250,100 325,300 Q 400,150 425,300") pathani_duration#(pathAni#, 3.0) pathani_interpolation#(pathAni#, "Linear") pathani_autoreverse#(pathAni#, 1) pathani_loop#(pathAni#, 1) pathani_start(pathAni#) form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
Best Practices
| Practice | Why |
|---|---|
Always start paths with M x,y | Required — defines the starting position on the path |
Use "Linear" interpolation for orbits and loops | Constant speed feels natural for continuous circular or looping motion |
Use Z to close looping paths | Creates a seamless return to start; essential for square/polygon paths |
Enable rotate = 1 for directional objects | Arrows, vehicles, fish, and similar shapes should face their travel direction |
Use two A arc commands for full circles | SVG arcs cannot draw a full 360° in one command; use two 180° arcs |
| Build long paths with string concatenation | Keeps code readable: p$ = p$ + "C ..." |
Use Q for bouncing trajectories | Quadratic curves create natural parabolic bounce arcs |
Use C / S for smooth S-curves | Cubic Béziers give the most control over curve shape |
Use clearpath# before setting a new path | Clean reset when dynamically changing paths at runtime |
| Uppercase commands for absolute, lowercase for relative | Relative is useful when reusing path segments at different offsets |
Quick Reference
| Function | Signature | Description |
|---|---|---|
pathani_error / errormsg$ / strerror$ / clearerror | various | Error handling (4) |
pathani#(parent#[, name$]) | pathani#@# / pathani#@#$ | Create (2 overloads) |
pathani_free(ani#) | pathani_free@# | Destroy |
pathani_start / stop / stopatcurrent | various | Playback control (3) |
pathani_path# / path$ / clearpath# | various | Path data (3) |
pathani_rotate# / rotate | various | Auto-rotation (2) |
pathani_duration / delay | various | Timing (4) |
pathani_animationtype / interpolation | various | Easing & curves (4) |
pathani_autoreverse / inverse / loop / enabled | various | Behavior flags (8) |
pathani_running / normalizedtime / name$ | various | State queries (3) |
pathani_trigger / triggerinverse | various | Automatic triggers (4) |
pathani_onfinish / onprocess / clearcallbacks# | various | Events (5) |
43 functions. Part of the Plan9Basic Animation library system.