Crate glissade

source ·
Expand description

§Glissade

Tests Status Build Status Clippy Status Format Status Pages Status

Glissade is a Rust animations and transitions library. It’s framework-agnostic with optional euclid, nalgebra, cgmath, and palette support. To make it work, you need to enable the corresponding feature.

The lib contains two main types: Animation and Inertial.

  • Animation contains Keyframes and can be used in cases when we know start, end, and in between points.
  • Inertial can be used to make an object smoothly follow a target value. For example, a particle following a cursor. Background color changing smoothly on theme change.

It also contains a set of easing functions to make animations more natural. See the Easing enum for more details.

Most of the methods receive time as a parameter to allow testing without mocks, and have a consistent behavior during a single animation frame. It’s expected that time is received, for example, from Instant::now() once in the beginning of the frame, and used lately during the frame rendering.

Any type that implements Time trait can be used as a time type. By default, it’s implemented for std::time::Instant, std::time::SystemTime, f32, and f64. It’s also implemented for web_time::* if "web-time" feature is enabled. It’s recommended to use web_time::Instant and web_time::Duration as a time type in most cases.

Animation can be applied to any type that implements Mix trait. This trait is used to interpolate between two values. Mix trait is implemented for common types like f32, f64, bool, i8 - i64, u8 - u64, Option<T: Mix>, and tuples like (Mix, Mix), (Mix, Mix, Mix), etc. It’s also implemented for some popular libraries: nalgebra, euclid, cgmath, and palette.

The full documentation is available on docs.rs.

§Derive macro

The library contains a derive macro to implement the Mix trait for structs and tuples.

use glissade::Mix;
#[derive(Mix, PartialEq, Debug)]
struct Touch {
   x: f32,
   y: f32,
   pressure: u8,
}
let touch1 = Touch { x: 0.0, y: 0.0, pressure: 0 };
let touch2 = Touch { x: 100.0, y: 100.0, pressure: 200 };
let touch_mix = touch1.mix(touch2, 0.5);
assert_eq!(touch_mix, Touch { x: 50.0, y: 50.0, pressure: 100 });

§Cargo features

  • "derive" - enables derive macro for Mix trait. Enabled by default.
  • "euclid" - enables euclid vectors, rotations, etc. animation.
  • "nalgebra" - enables nalgebra vectors, matrices, transformations, etc. animation.
  • "cgmath" - enables cgmath vectors, matrices, etc. animation.
  • "palette" - enables palette colors interpolation.
  • "web-time" - use web_time::* instead of std::time::* for Instant and Duration types. It doesn’t change anything for desktop platforms, but allows to use the same code for WASM. Enabled by default.

§Examples

§Live

  • Animating a shape using Inertial [Live] [Source]
  • A set of particles following the cursor made with Inertial [Live] [Source]

§Simple two-step animation

use glissade::{keyframes, Animated, Easing, Keyframes};
use std::thread::sleep;
use std::time::{Duration, Instant};

const STEPS_COUNT: u32 = 10;
const STEP: Duration = Duration::from_millis(3500 / STEPS_COUNT as u64);

fn main() {
    let start_time = Instant::now();

    // Transition consists of two steps:
    // 1. from 0.0 to 10.0 in 1 second linearly,
    // 2. and then go to 5.0 with easing function.
    let animation = keyframes(0.0)
        .go_to(10.0, Duration::from_secs(1))
        .ease_to(5.0, Duration::from_secs(2), Easing::QuadraticInOut)
        .run(start_time);

    for _ in 0..STEPS_COUNT {
        println!(
            "{:.2}s: {:.4}",
            start_time.elapsed().as_secs_f64(),
            animation.get(Instant::now())
        );
        sleep(STEP);
    }
}

Prints the following output:

0.00s: 0.0000
0.35s: 3.5000
0.70s: 7.0000
1.05s: 9.9935
1.40s: 9.5980
1.75s: 8.5862
2.10s: 7.0160
2.45s: 5.7480
2.80s: 5.0970
3.15s: 5.0000

Try it yourself with cargo run -p console-transition, or view the source code in ./examples/console-transition.

§Smoothly change color

use glissade::{Animated, Inertial};

type Color = (u8, u8, u8);

const RED: Color = (255, 0, 0);
const GREEN: Color = (0, 255, 0);
const BLUE: Color = (0, 0, 255);

fn main() {
    let mut color = Inertial::new(RED);

    println!("Static color for one second.");
    for time in [0.0, 0.25, 0.5, 0.75, 1.0].iter().copied() {
        println!("{:.2}s: {:?}", time, color.get(time));
    }

    println!("\nThen go to green in 2 seconds.");
    color = color.go_to(GREEN, 1.0, 2.0);
    for time in [1.25, 1.5, 1.75, 2.0].iter().copied() {
        println!("{:.2}s: {:?}", time, color.get(time));
    }

    println!("\nIn the middle of the transition change direction to blue.");
    color = color.go_to(BLUE, 2.0, 2.0);
    for time in [2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.25, 4.5]
        .iter()
        .copied()
    {
        println!("{:.2}s: {:?}", time, color.get(time));
    }
}

Prints the following output:

Static color for one second.
0.00s: (255, 0, 0)
0.25s: (255, 0, 0)
0.50s: (255, 0, 0)
0.75s: (255, 0, 0)
1.00s: (255, 0, 0)

Then go to green in 2 seconds.
1.25s: (247, 8, 0)
1.50s: (223, 32, 0)
1.75s: (183, 72, 0)
2.00s: (128, 128, 0)

In the middle of the transition change direction to blue.
2.25s: (70, 177, 8)
2.50s: (28, 195, 32)
2.75s: (6, 178, 72)
3.00s: (0, 128, 128)
3.25s: (0, 72, 183)
3.50s: (0, 32, 223)
3.75s: (0, 8, 247)
4.00s: (0, 0, 255)
4.25s: (0, 0, 255)
4.50s: (0, 0, 255)

Try it yourself with cargo run -p console-inertial, or view the source code in ./examples/console-inertial.

§License

This project is licensed under the MIT License - see the LICENSE.md file for details.

Structs§

  • Running keyframes animation started at a specific time.
  • A value that smoothly goes to the target during a specific time. The target can be changed at any time. No jumps will occur. It’s expected that time is always increasing. Every method receives current_time as a parameter to allow testing, and have a consistent behavior during a single animation frame.

Enums§

  • The easing functions are used to provide a smooth transition between two values over time. See: https://easings.net/ for more information.

Traits§

  • An animated value that changes over time. It’s a common trait for Animation and Inertial.
  • A transition of a value over time. It works like an animation template, or set of keyframes. A good point to start building Animation is the keyframes function.
  • Mix trait for linear interpolation between two values.
  • Time trait should be implemented for types that represent animation time. It’s implemented for f32, f64, std::time::Instant, and std::time::SystemTime by default. You can implement it for your own types.
  • Positive time difference

Functions§

  • Start Animation constructing with this function. It receives the initial value.

Derive Macros§

  • Derive the Mix trait for a struct. It interpolates each field of the struct with the Mix trait.