Rust动画与关键帧插值库keyframe的使用,高效实现平滑动画过渡和复杂曲线运动效果

Rust动画与关键帧插值库keyframe的使用,高效实现平滑动画过渡和复杂曲线运动效果

简介

keyframe是一个简单的Rust动画库,提供了以下功能:

  1. 多种缓动函数,包括用户定义的贝塞尔曲线(类似CSS的cubic-bezier)和可关键帧化的曲线
  2. 动画序列(类似CSS的@keyframes
  3. 与mint库集成,支持2D/3D/4D数据结构(点、矩形、颜色等)

基本用法

补间动画

使用keyframe::ease(function, from, to, time)在两个值之间进行补间动画:

use keyframe::{ease, functions::EaseInOut};

fn example() -> f64 {
    let a = 0.0;
    let b = 2.0;
    let time = 0.5;

    ease(EaseInOut, a, b, time)
}

动画序列

使用keyframe::AnimationSequence创建更复杂的动画:

use keyframe::{keyframes, Keyframe, AnimationSequence};

fn example() {
    // (value, time) 或 (value, time, function)
    let mut sequence = keyframes![
        (0.5, 0.0), // <-- 从0.0到0.3使用EaseInOut
        (1.5, 0.3, Linear), // <-- 从0.3到1.0使用Linear
        (2.5, 1.0) // <-- 这里的缓动函数不会使用,因为已经是最后了
    ];

    sequence.advance_by(0.65);

    assert_eq!(sequence.now(), 2.0);
    assert_eq!(sequence.duration(), 1.0);
}

自定义结构

use keyframe::mint::Point2;
// 这个宏适用于任何只包含实现"CanTween"类型的结构体
use keyframe_derive::CanTween;

#[derive(CanTween)]
struct MySubStructure {
    a: f32
}

#[derive(CanTween)]
struct MyStructure {
    a: f64,
    b: Point2<f64>,
    c: f32,
    d: [MySubStructure; N] // 数组长度由类型系统保证
}

// 也适用于无名结构体
#[derive(CanTween)]
struct UnnamedStructure(MyStructure, f64);

完整示例

下面是一个展示颜色渐变动画的完整示例:

use keyframe::{keyframes, AnimationSequence, functions::{EaseInOut, BounceOut}};
use keyframe::mint::Vector4;

fn main() {
    // 创建一个颜色渐变的动画序列
    let mut color_animation = keyframes![
        // 从红色开始,使用EaseInOut缓动
        (Vector4 { x: 1.0, y: 0.0, z: 0.0, w: 1.0 }, 0.0, EaseInOut),
        // 过渡到绿色
        (Vector4 { x: 0.0, y: 1.0, z: 0.0, w: 1.0 }, 0.3),
        // 过渡到蓝色,使用BounceOut特效
        (Vector4 { x: 0.0, y: 0.0, z: 1.0, w: 1.0 }, 0.7, BounceOut),
        // 最后回到红色
        (Vector4 { x: 1.0, y: 0.0, z: 0.0, w: 1.0 }, 1.0)
    ];

    println!("颜色渐变动画示例:");
    for i in 0..=10 {
        let progress = i as f32 / 10.0;
        color_animation.advance_to(progress);
        let current_color = color_animation.now();
        println!("进度: {:.1}, RGBA: ({:.2}, {:.2}, {:.2}, {:.2})", 
                progress, current_color.x, current_color.y, current_color.z, current_color.w);
    }
}

注意事项

  1. 库提供了多种内置缓动函数,包括EaseIn、EaseOut、EaseInOut、Linear等
  2. 可以创建自定义的缓动函数来实现特殊的动画效果
  3. 动画序列可以包含任意数量的关键帧
  4. 支持各种数值类型和数据结构,包括mint库中的2D/3D/4D类型

通过合理使用keyframe库,可以轻松实现复杂的动画效果和平滑的过渡效果。


1 回复

Rust动画与关键帧插值库keyframe使用指南

keyframe是一个轻量级的Rust动画库,专门用于处理关键帧动画和插值计算,能够高效实现平滑动画过渡和复杂曲线运动效果。

主要特性

  • 支持多种插值方法:线性、缓入、缓出、贝塞尔曲线等
  • 内置多种常用缓动函数
  • 支持自定义插值器
  • 类型安全的动画系统
  • 零运行时成本抽象

安装

Cargo.toml中添加依赖:

[dependencies]
keyframe = "1.0"

基本用法

1. 创建简单动画

use keyframe::{keyframes, AnimationSequence};
use keyframe::functions::*;

fn main() {
    // 创建关键帧序列
    let mut sequence = keyframes![
        (0.0, 0.0, Linear),  // 时间0.0秒,值0.0
        (1.0, 10.0, EaseInOut)  // 时间1.0秒,值10.0
    ];
    
    // 获取任意时间的插值
    println!("Value at 0.5s: {}", sequence.now(0.5));
}

2. 使用内置缓动函数

use keyframe::functions::*;

let sequence = keyframes![
    (0.0, 0.0, Linear),
    (1.0, 100.0, EaseInOutCubic),
    (2.0, 50.0, EaseOutElastic)
];

3. 复杂动画序列

use keyframe::{AnimationSequence, keyframes};
use keyframe::functions::*;

let mut sequence = AnimationSequence::new();

sequence.append(keyframes![
    (0.0, 0.0, Linear),
    (1.0, 100.0, EaseInOutQuad)
]);

sequence.append(keyframes![
    (0.0, 100.0, Linear),
    (1.0, 0.0, EaseOutBounce)
]);

// 前进到特定时间点
sequence.advance_to(1.5);
println!("Current value: {}", sequence.now());

高级功能

自定义插值器

use keyframe::{CanTween, Keyframe, AnimationSequence};
use std::ops::Mul;

#[derive(Clone, Debug)]
struct Color {
    r: f64,
    g: f64,
    b: f64,
}

impl CanTween for Color {
    fn ease(from: Self, to: Self, time: impl Mul<f64, Output = f64>) -> Self {
        Color {
            r: from.r + (to.r - from.r) * *time,
            g: from.g + (to.g - from.g) * *time,
            b: from.b + (to.b - from.b) * *time,
        }
    }
}

let mut color_animation = AnimationSequence::new();
color_animation.append(Keyframe::new(Color { r: 1.0, g: 0.0, b: 0.0 }, 0.0, Linear));
color_animation.append(Keyframe::new(Color { r: 0.0, g: 1.0, b: 0.0 }, 1.0, EaseInOut));

贝塞尔曲线插值

use keyframe::{keyframes, functions::BezierEasing};

let bezier = BezierEasing::new(0.42, 0.0, 0.58, 1.0);
let sequence = keyframes![
    (0.极,值0.0
        (1.0, 100.0, bezier)
];

性能建议

  1. 对于频繁调用的动画,考虑重用AnimationSequence而不是每次重新创建
  2. 使用derive(CanTween)为自定义类型自动实现插值
  3. 在游戏循环中,使用advance_and_maybe_wrap方法来处理循环动画

完整示例:2D物体动画

use keyframe::{keyframes, AnimationSequence};
use keyframe::functions::*;

struct GameObject {
    x: f64,
    y: f64,
    scale: f64,
    rotation: f64,
}

fn main() {
    // 创建位置动画
    let mut x_anim = keyframes![
        (0.0, 0.0, Linear),
        (2.0, 300.0, EaseOutElastic),
        (4.0, 100.0, EaseInOutBack)
    ];
    
    let mut y_anim = keyframes![
        (0.0, 0.0, Linear),
        (1.0, 200.0, EaseOutBounce),
        (3.0, 50.0, EaseInQuad)
    ];
    
    // 创建缩放动画
    let mut scale_anim = keyframes![
        (0.0, 1.0, Linear),
        (1.5, 1.5, EaseOutElastic),
        (3.0, 0.8, EaseInOutBack)
    ];
    
    // 模拟游戏循环
    let mut time = 0.0;
    while time <= 4.0 {
        let mut obj = GameObject {
            x: x_anim.now(time),
            y: y_anim.now(time),
            scale: scale_anim.now(time),
            rotation: 0.0,
        };
        
        println!(
            "Time: {:.1}s | Position: ({:.1, {:.1}) | Scale: {:.2}",
            time, obj.x, obj.y, obj.scale
        );
        
        time += 0.1;
    }
}

keyframe库提供了强大而灵活的工具来创建各种动画效果,从简单的线性过渡到复杂的弹性运动都可以轻松实现。通过组合不同的关键帧和缓动函数,你可以为你的Rust应用或游戏创建流畅的动画体验。

回到顶部