motus-tween 0.1.0

Tween<T> single-value animation for the Motus animation library.
Documentation
  • Coverage
  • 100%
    44 out of 44 items documented9 out of 25 items with examples
  • Size
  • Source code size: 37.13 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 447.81 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 10s Average build duration of successful builds.
  • all releases: 10s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • AarambhDevHub/animato
    22 1 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • aarambh-darshan

Motus

Latin: mōtus — motion, movement, impulse.

Crates.io Docs.rs CI License: MIT OR Apache-2.0 v0.1.0 ✅

A professional-grade, renderer-agnostic animation library for Rust.

Zero mandatory dependencies. no_std-ready. Built as a clean Cargo workspace — use only the crates you need.

Works everywhere: TUIs, Web (WASM), Bevy games, embedded targets, CLI tools, and native desktop apps.


Why Motus?

Most Rust animation crates are either too minimal (just easing functions) or too coupled to a specific renderer or framework. Motus sits in between:

  • Computes values, never renders. You own the render loop; Motus just tells you what the value is at each frame.
  • Workspace architecture. Each concern lives in its own crate. You don't download wgpu just to animate a progress bar.
  • no_std core. The trait system, all easing functions, Tween<T>, and Spring compile without std or heap allocation.
  • Builder pattern everywhere. No positional argument confusion; every optional field has a sensible default.
  • Generic over your types. Implement Interpolate once and animate any value — f32, [f32; 3], your custom color type, anything.

Crates

Shipped in v0.1.0:

Crate Description no_std
motus-core Traits (Interpolate, Animatable, Update) + 31 easing functions
motus-tween Tween<T>, Loop, TweenState, TweenBuilder
motus-spring Spring, SpringN<T>, SpringConfig presets
motus-driver AnimationDriver, Clock, WallClock, MockClock
motus Facade crate — re-exports all of the above

Planned in future versions (see ROADMAP.md):

Crate Version Description
motus-timeline v0.2.0 Timeline, Sequence, stagger, At positioning
motus-path v0.4.0 Bezier, CatmullRom, SVG path parser, shape morph
motus-physics v0.5.0 Inertia, DragState, GestureRecognizer
motus-color v0.6.0 Perceptual color interpolation (Lab, Oklch, Linear)
motus-bevy v0.7.0 MotusPlugin for Bevy
motus-wasm v0.7.0 RafDriver, FLIP, SplitText, ScrollSmoother
motus-gpu v0.9.0 GpuAnimationBatch — 10K+ tweens per frame on GPU

Most users only need the facade:

[dependencies]
motus = "0.1"

Quick Start

Animate a single value

use motus::{Tween, Easing, Update};

let mut tween = Tween::new(0.0_f32, 100.0)
    .duration(1.0)
    .easing(Easing::EaseOutCubic)
    .build();

// In your update loop — pass dt (seconds since last frame):
tween.update(0.016); // ~60fps tick
println!("{}", tween.value()); // current interpolated value

Spring physics

use motus::{Spring, SpringConfig, Update};

let mut spring = Spring::new(SpringConfig::wobbly());
spring.set_target(200.0);

// Animate until settled:
while !spring.is_settled() {
    spring.update(1.0 / 60.0);
}
println!("settled at {}", spring.position());

Loop modes

use motus::{Tween, Loop, Easing, Update};

let mut tween = Tween::new(0.0_f32, 100.0)
    .duration(1.0)
    .easing(Easing::EaseInOutSine)
    .looping(Loop::PingPong)
    .build();

for _ in 0..600 {
    tween.update(1.0 / 60.0);
}
println!("{}", tween.value()); // oscillates 0 ↔ 100

AnimationDriver — manage many animations

use motus::{Tween, Easing, AnimationDriver, WallClock, Clock};

let mut driver = AnimationDriver::new();
let mut clock  = WallClock::new();

let id = driver.add(
    Tween::new(0.0_f32, 1.0).duration(2.0).easing(Easing::EaseInOutSine).build()
);

loop {
    let dt = clock.delta();
    driver.tick(dt);

    if !driver.is_active(id) { break; }
}

Multi-dimensional spring

use motus::{SpringN, SpringConfig, Update};

let mut spring: SpringN<[f32; 3]> = SpringN::new(SpringConfig::stiff(), [0.0; 3]);
spring.set_target([100.0, 200.0, 300.0]);

while !spring.is_settled() {
    spring.update(1.0 / 60.0);
}
let [x, y, z] = spring.position();

Feature Flags

[dependencies]
motus = { version = "0.1", features = ["serde"] }

v0.1.0 features:

Feature What it adds
default std + tween + spring + driver
std Wall clock, heap-backed SpringN<T>
tween Tween<T>, Loop, TweenState
spring Spring, SpringN<T>, all presets
driver AnimationDriver, Clock variants
serde Serialize/Deserialize on all public types

Features planned for future versions:

Feature Version What it adds
timeline v0.2.0 Timeline, Sequence, stagger
path v0.4.0 Bezier, MotionPath, SVG parser
physics v0.5.0 Inertia, DragState, GestureRecognizer
color v0.6.0 Perceptual color interpolation via palette
bevy v0.7.0 MotusPlugin for Bevy
wasm v0.7.0 RafDriver + WASM bindings
gpu v0.9.0 GpuAnimationBatch via wgpu
tokio v0.3.0 .wait().await on Timeline completion

no_std usage

[dependencies]
motus-core   = { version = "0.1", default-features = false }
motus-tween  = { version = "0.1", default-features = false }
motus-spring = { version = "0.1", default-features = false }

Available in no_std: Easing, Tween<T>, Spring, SpringN<T>, all Interpolate blanket impls.


Easing Functions

31 easing functions available as Easing::EaseOutCubic (enum) or ease_out_cubic(t) (free function):

Group Variants
Linear Linear
Polynomial EaseIn/Out/InOut × Quad, Cubic, Quart, Quint (12 total)
Sinusoidal EaseIn/Out/InOutSine
Exponential EaseIn/Out/InOutExpo
Circular EaseIn/Out/InOutCirc
Back (overshoot) EaseIn/Out/InOutBack
Elastic EaseIn/Out/InOutElastic
Bounce EaseIn/Out/InOutBounce
Escape hatch Custom(fn(f32) -> f32)

Advanced variants (CubicBezier, Steps, RoughEase, etc.) are planned for v0.3.0+.


Bevy Integration

use bevy::prelude::*;
use motus_bevy::{MotusPlugin, TweenCompleted};
use motus::Tween;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(MotusPlugin)
        .add_systems(Startup, spawn_animated)
        .add_systems(Update, on_tween_done)
        .run();
}

fn spawn_animated(mut commands: Commands) {
    commands.spawn((
        SpriteBundle::default(),
        Tween::new([0.0_f32, 0.0], [300.0, 0.0])
            .duration(1.0)
            .easing(Easing::EaseOutBack)
            .build(),
    ));
}

fn on_tween_done(mut events: EventReader<TweenCompleted>) {
    for ev in events.read() {
        println!("Entity {:?} finished animating", ev.entity);
    }
}

WASM Integration

[dependencies]
motus = { version = "0.1", features = ["wasm"] }
use wasm_bindgen::prelude::*;
use motus::{Tween, Easing};
use motus::wasm::RafDriver;

#[wasm_bindgen]
pub struct App {
    tween:  Tween<f32>,
    driver: RafDriver,
}

#[wasm_bindgen]
impl App {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Self {
        Self {
            tween:  Tween::new(0.0_f32, 500.0).duration(1.5).easing(Easing::EaseOutBounce).build(),
            driver: RafDriver::new(),
        }
    }

    // Call from JavaScript requestAnimationFrame callback:
    pub fn tick(&mut self, timestamp_ms: f64) { self.driver.tick(timestamp_ms); }
    pub fn value(&self) -> f32 { self.tween.value() }
}

Build: wasm-pack build --target web --features wasm


Architecture

Motus is a Cargo workspace of 12 focused crates. See ARCHITECTURE.md for the full design document — crate boundaries, module specifications, type system design, data flow diagrams, and performance guidelines.


Examples

# v0.1.0 examples (available now):
cargo run --example basic_tween
cargo run --example spring_demo

# Coming in future versions:
# cargo run --example timeline_sequence   # v0.2.0
# cargo run --example motion_path         # v0.4.0
# cargo run --example color_animation     # v0.6.0
# cargo run --example tui_progress        # v0.7.0

Running Tests

# All tests, all features:
cargo test --workspace --all-features

# no_std check:
cargo test --workspace --no-default-features

# Benchmarks:
cargo bench

# Docs:
cargo doc --workspace --all-features --open

Roadmap

See ROADMAP.md for the full versioned plan from v0.1.0 to v1.0.0.

Current status: v0.1.0 — Foundation ✅ shipped

Next Milestone
v0.2.0 Composition — Timeline, Sequence, KeyframeTrack, stagger
v0.3.0 Control — callbacks, time scale, CubicBezier/Steps easing
v0.4.0 Paths — Bezier, SVG, motion paths

Contributing

Contributions are welcome — bug reports, feature suggestions, documentation improvements, and pull requests.

See CONTRIBUTING.md for how to set up the workspace, run tests, and submit a PR.


Support

If Motus is useful to you, consider supporting ongoing development:


License

Licensed under either of:

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project shall be dual-licensed as above, without any additional terms or conditions.