Rust动画过渡效果库simple-easing的使用,提供平滑的缓动函数实现动画效果
simple-easing
这个包包含一组简单的缓动函数,用于实现动画的平滑过渡效果。
安装
在项目目录中运行以下Cargo命令:
cargo add simple-easing
或者在Cargo.toml中添加以下行:
simple-easing = "1.0.1"
使用示例
下面是一个使用simple-easing库实现平滑动画过渡效果的完整示例:
use simple_easing::{linear, quad_in, quad_out, quad_in_out};
fn main() {
// 定义动画持续时间(毫秒)
let duration = 1000;
// 定义动画开始和结束值
let start_value = 0.0;
let end_value = 100.0;
// 模拟动画帧更新
for t in 0..=10 {
// 计算当前时间进度(0.0到1.0之间)
let progress = t as f32 / 10.0;
// 使用不同的缓动函数计算当前值
let linear_val = linear(progress, start_value, end_value - start_value, 1.0);
let quad_in_val = quad_in(progress, start_value, end_value - start_value, 1.0);
let quad_out_val = quad_out(progress, start_value, end_value - start_value, 1.0);
let quad_in_out_val = quad_in_out(progress, start_value, end_value - start_value, 1.0);
println!("Progress: {:.1}%", progress * 100.0);
println!("Linear: {:.2}", linear_val);
println!("Quad In: {:.2}", quad_in_val);
println!("Quad Out: {:.2}", quad_out_val);
println!("Quad In-Out: {:.2}", quad_in_out_val);
println!("------------------");
}
}
完整示例代码
下面是一个更完整的示例,展示了如何使用多种缓动函数创建动画效果:
use simple_easing::{
linear, quad_in, quad_out, quad_in_out,
cubic_in, cubic_out, cubic_in_out,
sine_in, sine_out, sine_in_out,
expo_in, expo_out, expo_in_out
};
fn main() {
// 动画参数设置
let duration_ms = 2000;
let frames = 20;
let start_val = 0.0f32;
let end_val = 200.0f32;
let change = end_val - start_val;
println!("Animation Demo - Easing Functions Comparison");
println!("Duration: {}ms | Frames: {}", duration_ms, frames);
println!("Value Range: {} to {}", start_val, end_val);
println!("=============================================");
// 模拟动画帧
for frame in 0..=frames {
let progress = frame as f32 / frames as f32;
// 计算不同缓动函数的值
let vals = vec![
("Linear", linear(progress, start_val, change, 1.0)),
("Quad In", quad_in(progress, start_val, change, 1.0)),
("Quad Out", quad_out(progress, start_val, change, 1.0)),
("Cubic In", cubic_in(progress, start_val, change, 1.0)),
("Cubic Out", cubic_out(progress, start_val, change, 1.0)),
("Sine In", sine_in(progress, start_val, change, 1.0)),
("Sine Out", sine_out(progress, start_val, change, 1.0)),
("Expo In", expo_in(progress, start_val, change, 1.0)),
("Expo Out", expo_out(progress, start_val, change, 1.0)),
];
// 输出当前帧的动画值
println!("\nFrame {} (Progress: {:.1}%)", frame, progress * 100.0);
for (name, val) in vals {
println!("{:9}: {:6.1} | {}", name, val, progress_bar(val, end_val));
}
}
}
// 辅助函数:创建简单的进度条可视化
fn progress_bar(current: f32, max: f32) -> String {
let width = 20;
let filled = (current / max * width as f32).round() as usize;
let empty = width - filled;
format!("[{}{}]", "=".repeat(filled), " ".repeat(empty))
}
可用的缓动函数
该库提供了多种缓动函数,包括:
linear
- 线性缓动(无加速)quad_in
- 二次方缓入(开始慢)quad_out
- 二次方缓出(结束慢)quad_in_out
- 二次方缓入缓出cubic_in
- 三次方缓入cubic_out
- 三次方缓出cubic_in_out
- 三次方缓入缓出quart_in
- 四次方缓入quart_out
- 四次方缓出quart_in_out
- 四次方缓入缓出quint_in
- 五次方缓入quint_out
- 五次方缓出quint_in_out
- 五次方缓入缓出sine_in
- 正弦缓入sine_out
- 正弦缓出sine_in_out
- 正弦缓入缓出expo_in
- 指数缓入expo_out
- 指数缓出expo_in_out
- 指数缓入缓出circ_in
- 圆形缓入circ_out
- 圆形缓出circ_in_out
- 圆形缓入缓出
许可证
MIT 或 Apache-2.0
1 回复
Rust动画过渡效果库simple-easing使用指南
simple-easing
是一个轻量级的Rust库,提供了多种缓动函数(easing functions)来实现平滑的动画过渡效果。这些函数可以帮助你在UI动画、游戏开发或其他需要平滑过渡的场景中创建更自然的运动效果。
安装
在Cargo.toml
中添加依赖:
[dependencies]
simple-easing = "0.2"
基本用法
simple-easing
提供了多种缓动函数,每种都有三种变体:ease_in
、ease_out
和ease_in_out
。
示例:基本缓动函数使用
use simple_easing::{quadratic, cubic, sine};
fn main() {
// 线性插值示例
let t = 0.5; // 时间进度,范围[0.0, 1.0]
let value = sine::ease_in_out(t);
println!("Sine ease-in-out at t=0.5: {}", value);
// 计算动画过程中的值
let start = 0.0;
let end = 100.0;
let current_value = start + (end - start) * cubic::ease_out(t);
println!("Current animated value: {}", current_value);
}
支持的缓动函数类型
库中包含了以下缓动函数:
- 线性(linear)
- 二次(quadratic)
- 三次(cubic)
- 四次(quartic)
- 五次(quintic)
- 正弦(sine)
- 圆形(circular)
- 指数(exponential)
- 弹性(elastic)
- 反弹(back)
- 弹跳(bounce)
示例:多种缓动函数比较
use simple_easing::{quadratic, cubic, sine, bounce};
fn compare_easings(t: f32) {
println!("t={}", t);
println!("Quadratic ease-in: {}", quadratic::ease_in(t));
println!("Cubic ease-out: {}", cubic::ease_out(t));
println!("Sine ease-in-out: {}", sine::ease_in_out(t));
println!("Bounce ease-out: {}", bounce::ease_out(t));
}
fn main() {
compare_easings(0.25);
compare_easings(0.5);
compare_easings(0.75);
}
实际动画应用示例
下面是一个使用simple-easing
实现简单动画循环的例子:
use simple_easing::cubic;
use std::thread;
use std::time::{Duration, Instant};
struct Animation {
start_time: Instant,
duration: f32,
start_value: f32,
end_value: f32,
}
impl Animation {
fn new(duration_secs: f32, start: f32, end: f32) -> Self {
Animation {
start_time: Instant::now(),
duration: duration_secs,
start_value: start,
end_value: end,
}
}
fn current_value(&self) -> f32 {
let elapsed = self.start_time.elapsed().as_secs_f32();
let t = (elapsed / self.duration).min(1.0); // 确保不超过1.0
// 使用缓动函数计算当前值
self.start_value + (self.end_value - self.start_value) * cubic::ease_in_out(t)
}
fn is_finished(&self) -> bool {
self.start_time.elapsed().as_secs_f32() >= self.duration
}
}
fn main() {
let mut anim = Animation::new(2.0, 0.0, 100.0);
while !anim.is_finished() {
println!("Current value: {:.2}", anim.current_value());
thread::sleep(Duration::from_millis(16)); // ~60fps
}
println!("Animation finished!");
}
自定义缓动函数
虽然simple-easing
提供了多种预设函数,但你也可以轻松创建自己的缓动函数:
// 自定义线性缓动函数
fn linear_ease(t: f32) -> f32 {
t
}
// 自定义"强弹性"缓动函数
fn strong_elastic_ease(t: f32) -> f32 {
if t == 0.0 || t == 1.0 {
return t;
}
let p = 0.3;
let s = p / 4.0;
let post_fix = 2.0_f32.powf(10.0 * (t - 1.0));
-(( (t - 1.0) * 2.0 * std::f32::consts::PI / p ).sin() * post_fix)
}
fn main() {
for t in 0..=10 {
let t = t as f32 * 0.1;
println!("t={:.1}, custom={:.4}", t, strong_elastic_ease(t));
}
}
性能考虑
simple-easing
是一个非常轻量级的库,所有函数都是纯数学计算,没有分配或系统调用,因此性能极高,适合在游戏循环或动画系统中频繁调用。
完整示例代码
下面是一个结合多种缓动函数的完整动画示例,展示如何创建一个简单的动画系统:
use simple_easing::{quadratic, cubic, sine, bounce, exponential};
use std::thread;
use std::time::{Duration, Instant};
// 动画状态枚举
enum AnimationState {
Running,
Paused,
Finished,
}
// 动画结构体
struct Animation {
start_time: Instant,
pause_time: Option<Instant>,
duration: f32,
start_value: f32,
end_value: f32,
state: AnimationState,
easing_fn: fn(f32) -> f32, // 缓动函数指针
}
impl Animation {
fn new(duration_secs: f32, start: f32, end: f32, easing_fn: fn(f32) -> f32) -> Self {
Animation {
start_time: Instant::now(),
pause_time: None,
duration: duration_secs,
start_value: start,
end_value: end,
state: AnimationState::Running,
easing_fn,
}
}
// 暂停动画
fn pause(&mut self) {
if let AnimationState::Running = self.state {
self.pause_time = Some(Instant::now());
self.state = AnimationState::Paused;
}
}
// 恢复动画
fn resume(&mut self) {
if let AnimationState::Paused = self.state {
if let Some(pause_time) = self.pause_time {
let pause_duration = pause_time - self.start_time;
self.start_time = Instant::now() - pause_duration;
self.pause_time = None;
self.state = AnimationState::Running;
}
}
}
// 获取当前值
fn current_value(&self) -> f32 {
let elapsed = match self.state {
AnimationState::Running => self.start_time.elapsed().as_secs_f32(),
AnimationState::Paused => self.pause_time.unwrap().duration_since(self.start_time).as_secs_f32(),
AnimationState::Finished => self.duration,
};
let t = (elapsed / self.duration).min(1.0);
let eased_t = (self.easing_fn)(t);
self.start_value + (self.end_value - self.start_value) * eased_t
}
// 检查动画是否完成
fn update_state(&mut self) {
if let AnimationState::Running = self.state {
if self.start_time.elapsed().as_secs_f32() >= self.duration {
self.state = AnimationState::Finished;
}
}
}
fn is_finished(&self) -> bool {
matches!(self.state, AnimationState::Finished)
}
}
fn main() {
// 创建多个使用不同缓动函数的动画
let mut animations = vec![
Animation::new(3.0, 0.0, 100.0, quadratic::ease_in_out),
Animation::new(2.5, 0.0, 200.0, cubic::ease_out),
Animation::new(4.0, 100.0, 0.0, bounce::ease_out),
Animation::new(3.5, 0.0, 150.0, exponential::ease_in),
];
// 模拟暂停/恢复
thread::sleep(Duration::from_secs_f32(1.0));
animations[0].pause();
thread::sleep(Duration::from_secs_f32(0.5));
animations[0].resume();
// 主循环
while animations.iter().any(|a| !a.is_finished()) {
for (i, anim) in animations.iter_mut().enumerate() {
anim.update_state();
if !anim.is_finished() {
println!("Anim {}: {:.2}", i, anim.current_value());
}
}
println!("---");
thread::sleep(Duration::from_millis(100)); // 10fps
}
println!("All animations finished!");
}
总结
simple-easing
为Rust开发者提供了简单易用的缓动函数集合,可以帮助你快速实现各种平滑动画效果。无论是UI元素动画、游戏对象移动还是其他需要渐进变化的场景,这个库都能提供很好的支持。