aura-anim-iced
Iced-first animation orchestration for applications that need coordinated property changes, state transitions, and screen-to-screen route motion.
This crate builds on Iced's public animation surface instead of replacing it.
User-facing APIs use Iced types such as iced::Color, iced::Vector,
iced::Size, iced::Rectangle, iced::Shadow, and
iced::animation::Easing.
The foundation layer covers:
- typed visual properties and sampled property snapshots;
- timing primitives that use Iced easing directly;
- property keyframes and timeline orchestration;
- a runtime that can gate Iced subscriptions while animations are active;
- Iced integration helpers for applying snapshots in
viewcode.
The v0.2 behavior layer adds:
PropertyTransitionandBehaviorRulefor animating value changes from the visual value currently on screen;StateAnimator,StateTransition, andStateTransitionSetfor mapping application state changes to timelines;- retargeting and interruption helpers that replace active animations without jumping back to stale target values;
RouteAnimatorand route screen transitions for outgoing and incoming route motion on separate targets.
Use Iced's Animation<T> for direct single-value animation. Use
aura-anim-iced when a UI state change needs coordinated opacity, transform,
size, color, shadow, hold, sequence, parallel, and runtime cleanup behavior.
Status
v0.2.1
Installation
Add the crate to an Iced application:
Enable optional diagnostics when runtime tick events should be visible through
tracing:
The same configuration can be written directly in Cargo.toml:
[]
= "0.2.1"
[]
= { = "0.2.1", = ["inspector"] }
Minimal Runtime Example
Store an AnimationRuntime in application state, register keyframes in update,
keep an Iced tick subscription active while the runtime is playing,
and convert tick output into view effects for one target.
use Instant;
use ;
In view, apply the sampled EffectSnapshot fields to the widget style,
layout, or wrapper code owned by the application.
Animatable Values
Public animation inputs use Iced value types wherever possible. The v0.1 value
model covers scalar values, iced::Vector, iced::Size, iced::Rectangle,
iced::Color, iced::Shadow, and transform-friendly values. Interpolation is
kept internal so application code works with typed properties and sampled
snapshots instead of implementing animation traits.
use ;
use Color;
let fade_and_color = new
.with_timing
.at
.at
.at
.at
.finish;
Property Tracks
Properties are identified by typed PropertySpec values. Built-in specs cover
opacity, translation, scale, size, padding, radius, colors, and shadow.
Applications can also define custom specs when an example or widget needs an
extra sampled value, such as a toast offset.
use ;
const TOAST_Y: =
new;
A PropertySnapshot stores sampled values for one target. When snapshots are
merged, later values replace earlier values with the same property spec and the
result is sorted by composition order.
Keyframes
Use KeyframesBuilder to collect property snapshots at normalized offsets from
0.0 to 1.0, then call finish() to compile them into a Keyframes value.
The finished keyframes own a Timing, so duration, easing, fill mode,
direction, iterations, and playback rate stay attached to the sampled property
data.
use ;
let popup_open = new
.with_timing
.at
.at
.at
.at
.at
.finish;
Duplicate offsets are merged. If the same property appears multiple times at the same offset, the later value wins.
Timeline Orchestration
Timelines combine keyframe tracks into sequences, parallel groups, and holds. Use sequences for lifecycle animation, parallel groups for coordinated property changes, and holds when a state should remain visible before the next step.
use ;
let enter = new;
let exit = new;
let toast_lifecycle = sequence;
Use Timeline::parallel when several tracks should sample at the same time.
Property collisions are resolved by insertion order inside the target snapshot.
Runtime Ticking
AnimationRuntime stores active keyframes and timelines by target ID. Register a
source in update, keep the returned handle if completion cleanup matters, and
route tick output back into application state.
use ;
let mut runtime = new;
let target = new;
let registration = runtime.register_keyframes;
let handle = registration.handle;
Each runtime tick returns target-scoped snapshots plus completed handles. Completed entries are removed automatically after their final output is emitted.
Iced Subscription Wiring
Use iced_ext::subscription to produce ticks only while the runtime has active
animations. Use iced_ext::update_tick to advance the runtime from an Iced tick
message. The runtime tick interval comes from TickPolicy.
use Instant;
use ;
For view code, convert tick output with tick_effect_snapshot_for when using
the built-in effect fields, or read AnimationTick::properties_for directly
when the application owns custom property specs.
Property Change Animation
Use PropertyTransition when an application value should animate whenever its
target changes. The first observed value seeds the stable baseline and does not
start an animation. Later different values register keyframes from the current
visual result to the new target.
BehaviorRule stores reusable property and timing settings. Bind it to one or
more targets to create independent transition trackers.
use ;
On each animation tick, merge the target snapshot into the value used by view
and let the transition clear its active handle when the runtime finishes:
use ;
The examples/behavior_width.rs example shows the same flow in a runnable Iced
application with controls for repeated value changes.
State-Driven Animation
Use StateAnimator when the application has a small state machine and each
state pair should launch a specific timeline. A StateTransitionSet stores the
known pairs and can also provide a fallback timeline for unlisted changes.
use ;
let mut runtime = new;
let target = new;
let mut animator = new;
let transitions = from_transitions
.with_fallback;
let registration = animator.transition_to;
assert!;
StateAnimator::current is updated as soon as a transition starts, while
active_transition and active_progress_at expose runtime metadata for loading
indicators, navigation locks, or diagnostics. Call handle_completion after
ticks when application code needs the cached active transition to match the
runtime exactly.
Retargeting And Interruption
Retargeting is for active animations that receive a new destination. The replacement starts from the active animation's last sampled visual value, not from the previous target.
let mut runtime = new;
let target = new;
let mut opacity = new
.with_timing;
opacity.transition_to;
opacity.transition_to;
// After one or more ticks, continue from the rendered value to the new target.
let retargeted = opacity.retarget_to;
Interruption is for cases where application code already knows the rendered value, such as drag cancellation or repeated user input. It can replace an active animation even when the destination has not changed.
let visual_opacity = 0.42;
let interrupted = opacity.interrupt_from_visual;
Both paths cancel the superseded runtime handle after registering the replacement. That prevents interrupted animations from later reporting completion or overriding the replacement output.
Route Transition Guide
Use route transitions when changing screens should animate the leaving and entering views independently.
- Store a
RouteAnimator<Route>in application state. - Give the outgoing and incoming screen layers separate
AnimationTargetIdvalues. - Build a
RouteScreenTransitionfrom an outgoing timeline and an incoming timeline orRouteIncomingMotion. - Register it with
transition_screens_with. - On ticks, merge snapshots for both screen targets into the effects used by
view. - When the route or incoming handle completes, clear temporary leaving-screen state.
use ;
let mut runtime = new;
let route_target = new;
let outgoing_target = new;
let incoming_target = new;
let mut animator = new;
let transition = with_incoming_motion;
let registration = animator.transition_screens_with;
assert!;
RouteIncomingMotion builds an incoming timeline that fades from 0.0 to 1.0
and translates from the supplied offset to iced::Vector::new(0.0, 0.0).
Repeated navigation replaces the active route, outgoing, and incoming handles
as a group, so stale screen animations are canceled together.
The examples/route_transition.rs example shows a complete Iced flow with
navigation buttons, overlaid screen cards, snapshot merging, and cleanup after
the incoming screen reaches its final state.