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

支持的缓动函数类型

库中包含了以下缓动函数:

  1. 线性(linear)
  2. 二次(quadratic)
  3. 三次(cubic)
  4. 四次(quartic)
  5. 五次(quintic)
  6. 正弦(sine)
  7. 圆形(circular)
  8. 指数(exponential)
  9. 弹性(elastic)
  10. 反弹(back)
  11. 弹跳(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元素动画、游戏对象移动还是其他需要渐进变化的场景,这个库都能提供很好的支持。

回到顶部