#animation #easing #transition #interpolation

glissade

Rust库,提供各种动画和过渡的实用工具

39个版本

0.1.39 2024年8月22日
0.1.38 2024年8月21日
0.1.36 2024年7月27日
0.1.16 2024年6月26日

#151 in 算法

Download history 239/week @ 2024-06-14 1163/week @ 2024-06-21 67/week @ 2024-06-28 25/week @ 2024-07-05 490/week @ 2024-07-12 1595/week @ 2024-07-19 466/week @ 2024-07-26 24/week @ 2024-08-02 102/week @ 2024-08-09 167/week @ 2024-08-16

962 每月下载

MIT 许可证

120KB
3K SLoC

Glissade

Tests Status Build Status Clippy Status Format Status Pages Status

Glissade是一个Rust动画和过渡库。它是框架无关的,具有可选的euclidnalgebracgmathglampalette支持。要使其正常工作,您需要启用相应的功能。

该库包含两个主要类型:AnimationInertial

  • Animation包含Keyframes,可以在我们知道起点、终点和中间点的情况下使用。它类似于CSS动画/关键帧
  • Inertial可用于使对象平滑地跟随目标值。它类似于CSS过渡。例如,一个跟随鼠标光标的粒子。在主题更改时背景色平滑变化。

它还包含一组缓动函数,使动画更自然。有关详细信息,请参阅Easing枚举。

为了使代码更通用,库中包含Animated特质,该特质为AnimationInertial实现。结合Stationary特质,在期望Animated的地方很容易传递静态值。默认情况下,它为原始类型(如数字或字符串)实现。

大多数方法都接收时间作为参数,以允许在无需模拟的情况下进行测试,并在单个动画帧中具有一致的行为。预期在帧开始时从Instant::now()接收时间一次,并在帧渲染过程中稍后使用。

任何实现了 Time 特性的类型都可以用作时间类型。默认情况下,它为 std::time::Instantstd::time::SystemTime、f32 和 f64 实现了该特性。如果启用了 "web-time" 功能,它也实现了 web_time::*。在大多数情况下,建议使用 web_time::Instantweb_time::Duration 作为时间类型。

动画可以应用于任何实现了 Mix 特性的类型。这个特性用于在两个值之间进行插值。Mix 特性为诸如 f32f64booli8 - i64u8 - u64Option<T: Mix> 以及元组如 (Mix, Mix)(Mix, Mix, Mix) 等常见类型实现了 Mix 特性。它还实现了某些流行的库:nalgebraeuclidcgmathglampalette

除了 Mix 之外,该库还包含 Distance 特性,用于计算两个值之间的距离。如果你的类型实现了 Distance,你可以使用 Keyframes::poly_to 来沿着路径动画一个值。请参阅 示例 部分以获取更多详细信息。

完整文档可在 docs.rs 上找到。

派生宏

该库包含一个派生宏,用于为结构和元组实现 Mix 特性。

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 功能

  • "derive" - 启用 Mix 特性的派生宏。默认启用。
  • "euclid" - 启用 euclid 向量、旋转等动画。
  • "nalgebra" - 启用 nalgebra 向量、矩阵、变换等动画。
  • "cgmath" - 启用 cgmath 向量、矩阵等动画。
  • "glam" - 启用 glam 向量、矩阵等动画。
  • "palette" - 启用 palette 颜色插值。
  • "web-time" - 使用 web_time::* 代替 std::time::* 进行 InstantDuration 类型。对于桌面平台没有影响,但允许在 WASM 中使用相同的代码。默认启用。

示例

实时

简单的两步 动画

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);
    }
}

它将输出以下内容

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

自己尝试使用 cargo run -p console-transition 或在 ./examples/console-transition 中查看源代码。

使用 惯性 平滑地更改颜色

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));
    }
}

它将输出以下内容

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)

自己尝试使用 cargo run -p console-inertial 或在 ./examples/console-inertial 中查看源代码。

动画惯性静态 使用相同的代码

use glissade::{keyframes, Animated, Inertial, Keyframes};
use std::fmt::Debug;

/// Print the values of an animated value at 0.0, 0.25, 0.5, 0.75, and 1.0.
/// Any value that implements `Animated` can be passed to this function.
/// So, it can accept animations, inertial, and stationary values.
pub fn print_1s_values<T: Clone + Debug>(value: impl Animated<T, f32>) {
    for i in [0.0, 0.25, 0.5, 0.75, 1.0].iter() {
        println!("{:.2}s: {:?}", i, value.get(*i));
    }
}

fn main() {
    println!("Animation:");
    let animation = keyframes((0.0, 2.0)).go_to((1.0, 3.0), 1.0).run(0.0);
    print_1s_values(animation);

    println!("\nInertial:");
    let inertial = Inertial::new(5.0).go_to(10.0, 0.0, 1.0);
    print_1s_values(inertial);

    println!("\nStationary:");
    let stationary = 42;
    print_1s_values(stationary);

    println!("\nMapped animation:");
    let animation = keyframes((0.0, 0.0))
        .go_to((100.0, 40.0), 1.0)
        .run(0.0)
        .map(|v| format!("left: {:.2}; top: {:.2};", v.0, v.1));
    print_1s_values(animation);
}

它将输出以下内容

Animation:
0.00s: (0.0, 2.0)
0.25s: (0.25, 2.25)
0.50s: (0.5, 2.5)
0.75s: (0.75, 2.75)
1.00s: (1.0, 3.0)

Inertial:
0.00s: 5.0
0.25s: 5.625
0.50s: 7.5
0.75s: 9.375
1.00s: 10.0

Stationary:
0.00s: 42
0.25s: 42
0.50s: 42
0.75s: 42
1.00s: 42

Mapped animation:
0.00s: "left: 0.00; top: 0.00;"
0.25s: "left: 25.00; top: 10.00;"
0.50s: "left: 50.00; top: 20.00;"
0.75s: "left: 75.00; top: 30.00;"
1.00s: "left: 100.00; top: 40.00;"

自己尝试使用 cargo run -p animated 或在 ./examples/animated 中查看源代码。

许可证

本项目采用 MIT 许可证 - 请参阅 LICENSE.md 文件以获取详细信息。

依赖项

~0–2.3MB
~55K SLoC