#animation #ui #interface

mina

A simple, expressive, framework-independent animation library for Rust

2 releases

0.1.1 Jun 15, 2023
0.1.0 Jun 15, 2023

#641 in GUI

Download history 7/week @ 2024-03-13 13/week @ 2024-03-27 54/week @ 2024-04-03 24/week @ 2024-04-10 9/week @ 2024-04-17 132/week @ 2024-04-24 55/week @ 2024-05-01 64/week @ 2024-05-08 22/week @ 2024-05-15 77/week @ 2024-05-22 47/week @ 2024-05-29 35/week @ 2024-06-05 70/week @ 2024-06-12 47/week @ 2024-06-19 75/week @ 2024-06-26

237 downloads per month

MIT license

130KB
1.5K SLoC

Mina

A simple, expressive, framework-independent animation library for Rust.

Features

  • Animate the properties of any standard struct.
  • Concise, CSS-like syntax for frames and timing.
  • State-based animators, à la CSS transitions.
  • Easings included, no math required.
  • GUI agnostic - you write the event loop and decide what the properties mean.

Goals

  • Simple: Creating and experimenting with animations should be easy.
  • Smooth: Animations should blend well, behave intuitively and never look janky.
  • Adaptable: Be able to animate simple properties out of the box, and less-simple properties with a few small tweaks.
  • Versatile: Incorporate into any app with a timer or event loop.

Timeline Example

Note: This is example, and all other examples on this page, include only the code used to create the timelines and/or animators. The full examples will always be available in the examples directory.

Moving Shape

#[derive(Animate)]
struct Shape {
    size: f32,
    #[animate] x: f32,
    #[animate] y: f32,
}

impl Shape {
    pub fn new(size: f32) -> Self {
        Shape { size, x: 0.0, y: 0.0 }
    }
}

let timeline = timeline!(Shape 5s infinite Easing::OutCubic
    from { x: -150.0, y: 60.0 }
    25% { x: 150.0, y: 60.0 }
    50% { x: 150.0, y: -60.0 }
    75% { x: -150.0, y: -60.0 }
    to { x: -150.0, y: 60.0 });

See the full example (uses nannou).

Animator Example

Fancy Widgets

#[derive(Animate, Clone, Debug, Default)]
struct Effects {
    background_alpha: f32,
    emission_alpha: f32,
    emission_scale: f32,
}

const EFFECT_SCALE: f32 = 2.0;

let animator = animator!(Effects {
    default(Interaction::None, {
        background_alpha: 0.5,
        emission_alpha: 0.25,
        emission_scale: 0.85
    }),
    Interaction::None => [
        0.5s Easing::OutCubic to { background_alpha: 0.5 },
        2s Easing::OutQuint infinite
            from { emission_alpha: 0.0, emission_scale: 0.0 }
            2% { emission_alpha: 0.15, emission_scale: 0.0 }
            5% { emission_scale: 0.85 } Easing::InOutCirc
            75% { emission_alpha: 0.0 }
            100% { emission_scale: EFFECT_SCALE },
    ],
    Interaction::Over => 0.5s Easing::OutCubic to {
        background_alpha: 0.8,
        emission_alpha: 0.0,
        emission_scale: 0.85,
    },
    Interaction::Down => [
        0.5s Easing::OutCubic to {
            background_alpha: 1.0,
            emission_alpha: 0.0,
            emission_scale: 0.85,
        },
        3s Easing::OutExpo
            1% { emission_scale: 1.05 }
            to { emission_alpha: 0.1, emission_scale: 1.5 }
    ]
});

The above is taken from the widget example using iced.

Roadmap

  • Standalone timelines with builder-style syntax
  • State-based animators
  • CSS-like grammar using proc macros
  • Tie up loose ends in macro grammar (per-keyframe easing, idents for duration/delay, etc.)
  • GUI-specific sub-crates for plug-and-play integration
  • Expand examples/integration crates to include more GUI libraries
  • Decouple from enum-map dependency
  • Built-in palette support (for color interpolation)

More Examples

Progress Indicator

Progress Indicator

Bevy Shapes and Sprites

Progress Indicator

Canvas Example (code coming soon!)

Canvas Example

Dependencies

~1.6–2.2MB
~50K SLoC