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 算法
962 每月下载
120KB
3K SLoC
Glissade
Glissade是一个Rust动画和过渡库。它是框架无关的,具有可选的euclid、nalgebra、cgmath、glam和palette支持。要使其正常工作,您需要启用相应的功能。
该库包含两个主要类型:Animation
和Inertial
。
Animation
包含Keyframes
,可以在我们知道起点、终点和中间点的情况下使用。它类似于CSS动画/关键帧。Inertial
可用于使对象平滑地跟随目标值。它类似于CSS过渡。例如,一个跟随鼠标光标的粒子。在主题更改时背景色平滑变化。
它还包含一组缓动函数,使动画更自然。有关详细信息,请参阅Easing
枚举。
为了使代码更通用,库中包含Animated
特质,该特质为Animation
和Inertial
实现。结合Stationary
特质,在期望Animated
的地方很容易传递静态值。默认情况下,它为原始类型(如数字或字符串)实现。
大多数方法都接收时间作为参数,以允许在无需模拟的情况下进行测试,并在单个动画帧中具有一致的行为。预期在帧开始时从Instant::now()
接收时间一次,并在帧渲染过程中稍后使用。
任何实现了 Time
特性的类型都可以用作时间类型。默认情况下,它为 std::time::Instant
、std::time::SystemTime
、f32 和 f64 实现了该特性。如果启用了 "web-time"
功能,它也实现了 web_time::*
。在大多数情况下,建议使用 web_time::Instant
和 web_time::Duration
作为时间类型。
动画可以应用于任何实现了 Mix
特性的类型。这个特性用于在两个值之间进行插值。Mix 特性为诸如 f32
、f64
、bool
、i8
- i64
、u8
- u64
、Option<T: Mix>
以及元组如 (Mix, Mix)
、(Mix, Mix, Mix)
等常见类型实现了 Mix 特性。它还实现了某些流行的库:nalgebra
、euclid
、cgmath
、glam
和 palette
。
除了 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::*
进行Instant
和Duration
类型。对于桌面平台没有影响,但允许在 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