#animation #smoothing #user #ui #speed #animator #interruptable

uianimator

为动画提供优雅响应用户输入的实用工具

2 个版本

0.1.1 2024 年 5 月 27 日
0.1.0 2024 年 5 月 27 日

#10 in #smoothing

MIT/Apache

13KB
166 行代码

uianimator

为您的 UI 提供平滑、可中断的动画

此包提供了 Animator 特性和一些默认动画器。您可以使用 get_valueset_target 函数与动画器交互。

为什么?

UI 动画通常存在以下两个问题之一

无法中断
如果用户打开了一个具有滑动动画的侧边栏,但在它完全打开之前关闭它,侧边栏可能会在播放滑动动画之前跳转到完全打开的状态,或者它将立即开始向相反方向移动,从 +x 速度变为 -x 速度,而不进行任何过渡。

或者 它们不准确且受帧/滴答率影响
第一个问题可以通过存储一个 speedposition 来部分解决,然后使用迭代算法来更新它们。然而,这意味着降低应用程序的帧率将使动画变慢。您可以通过使用 deltaTime 或在更多时间过去时移动更大的步骤来解决这个问题,但这仍然会使您的动画在不同设备上不一致。

uianimator 解决了这两个问题。它不使用迭代方法,并且所有默认动画器都是设计得如此,即您的动画当前值(位置)和其变化的速率(速度)都不会跳跃,而是平稳过渡,因此您的动画永远不会显得生硬。

用法

use std::time::{Duration, Instant};

use uianimator::{default_animator_f64_quadratic::DefaultAnimatorF64Quadratic, Animator};

fn main() {
    // start at 0.5 with a speed factor of 2.
    let mut animator = DefaultAnimatorF64Quadratic::new(0.5, 2.0);
    // smoothly transition from 0.5 to 2
    animator.set_target(2.0, Instant::now());
    loop {
        // repeatedly get the animator's current value and print it
        let val = animator.get_value(Instant::now());
        let count = (50.0 * val) as _;
        eprintln!(
            "val: {val:.2} | {}{} |",
            "=".repeat(count),
            " ".repeat(100 - count)
        );
        // once we reach 1, go to 0 instead. this simulates a user interrupting our animation.
        if val > 1.0 {
            animator.set_target(0.0, Instant::now());
        }
        // once we reach 0, exit
        if val == 0.0 {
            break;
        }
        std::thread::sleep(Duration::from_millis(50));
    }
}

动画器的初始 value0.5。然后它开始向 2.0 移动,但永远不会达到它,因为用户中断了动画,将新的 target 设置为 0
这是程序的输出(右侧代表 2 的值,左侧是 0

val: 0.50 |=============                                      |
val: 0.51 |=============                                      |
val: 0.54 |==============                                     |
val: 0.59 |===============                                    |
val: 0.66 |=================                                  |
val: 0.75 |===================                                |
val: 0.87 |======================                             |
val: 1.00 |=========================                          |
val: 1.15 |=============================                      |
val: 1.30 |=================================                  |
val: 1.43 |====================================               |
val: 1.55 |=======================================            |
val: 1.64 |=========================================          |
val: 1.71 |===========================================        |
val: 1.76 |============================================       |
val: 1.79 |=============================================      |
val: 1.80 |=============================================      |
val: 1.79 |=============================================      |
val: 1.76 |============================================       |
val: 1.71 |===========================================        |
val: 1.64 |=========================================          |
val: 1.55 |=======================================            |
val: 1.43 |====================================               |
val: 1.30 |=================================                  |
val: 1.15 |=============================                      |
val: 0.98 |========================                           |
val: 0.79 |====================                               |
val: 0.62 |================                                   |
val: 0.47 |============                                       |
val: 0.35 |=========                                          |
val: 0.24 |======                                             |
val: 0.15 |====                                               |
val: 0.08 |==                                                 |
val: 0.03 |=                                                  |
val: 0.01 |                                                   |
val: 0.00 |                                                   |

无运行时依赖项