跳转至

SOUI 数值动画 (ValueAnimator)

概述

SOUI 数值动画(SValueAnimator)是 SOUI 动画系统的基础类,提供了一个简单的时间引擎来运行动画并计算动画值。它是整个动画系统的核心,为其他动画类型(如属性动画和动画集合)提供基础功能。

SValueAnimator 本身不直接操作任何控件属性,而是通过计算随时间变化的数值,并在动画过程中通知监听器,从而实现各种动画效果。

核心概念

动画生命周期

数值动画具有明确的状态转换过程:

  1. idle(空闲):动画创建后的初始状态
  2. started(已启动):调用 start() 方法后进入此状态
  3. running(运行中):动画真正开始执行时的状态
  4. ended(结束):动画完成或被终止后的状态

关键属性

  • Duration(持续时间):动画从开始到结束需要的时间,默认为300毫秒
  • Start Delay(开始延迟):动画开始前的等待时间
  • Repeat Count(重复次数):动画重复执行的次数,可以设置为无限循环
  • Repeat Mode(重复模式):重复的方式,支持重启(RESTART)和反转(REVERSE)

主要方法

方法 描述
setDuration(long duration) 设置动画持续时间
getDuration() 获取动画持续时间
setStartDelay(long startDelay) 设置动画开始延迟
getStartDelay() 获取动画开始延迟
setRepeatCount(int value) 设置动画重复次数
getRepeatCount() 获取动画重复次数
setRepeatMode(RepeatMode value) 设置动画重复模式
getRepeatMode() 获取动画重复模式
start(ITimelineHandlersMgr *pContainer) 启动动画
end() 结束动画
reverse() 反转动画
isRunning() 检查动画是否正在运行
isStarted() 检查动画是否已启动

监听器

可以通过添加监听器来响应动画事件:

  • IAnimatorListener:监听动画的主要事件(开始、结束、重复)
  • IAnimatorUpdateListener:监听动画每一帧的更新

特定类型动画

SOUI 提供了几种常用的特定类型动画:

SIntAnimator

整数动画,用于在两个整数之间进行插值。

// 创建整数动画,从0到100,持续1秒
int values[] = {0, 100};
IValueAnimator* intAnimator = SPropertyAnimator::ofInt(pWindow, L"width", values, 2);
intAnimator->setDuration(1000);
intAnimator->start(pTimelineHandler);

SFloatAnimator

浮点数动画,用于在两个浮点数之间进行插值。

// 创建浮点动画,从0.0到1.0,持续500毫秒
float values[] = {0.0f, 1.0f};
IValueAnimator* floatAnimator = SPropertyAnimator::ofFloat(pWindow, L"alpha", values, 2);
floatAnimator->setDuration(500);
floatAnimator->start(pTimelineHandler);

SColorAnimator

颜色动画,用于在两种颜色之间进行插值。

// 创建颜色动画,从红色到绿色,持续2秒
COLORREF values[] = {RGB(255, 0, 0), RGB(0, 255, 0)};
IValueAnimator* colorAnimator = SPropertyAnimator::ofColorRef(pWindow, L"color", values, 2);
colorAnimator->setDuration(2000);
colorAnimator->start(pTimelineHandler);

TypeEvaluator 类型估值器

TypeEvaluator 是一个模板类,用于计算不同类型值之间的插值。系统已经为常用类型提供了默认实现:

  • 基本数值类型:使用线性插值
  • 颜色类型:使用色彩空间感知的插值算法
  • 点、尺寸、矩形等结构体:分别对各分量进行插值

对于自定义类型,可以通过特化模板来实现对应的估值逻辑。

插值器

插值器用于控制动画的变化速率,SOUI 提供了多种内置插值器:

  • 线性插值器(LinearInterpolator)
  • 加速插值器(AccelerateInterpolator)
  • 减速插值器(DecelerateInterpolator)
  • 加速减速插值器(AccelerateDecelerateInterpolator)
  • 弹跳插值器(BounceInterpolator)
  • 循环插值器(CycleInterpolator)

可以通过 setInterpolator() 方法设置动画的插值器:

SValueAnimator* animator = new SFloatAnimator();
animator->setInterpolator(new SAccelerateInterpolator());

使用示例

基本数值动画

// 创建一个浮点动画
SFloatAnimator* animator = new SFloatAnimator();
animator->setRange(0.0f, 1.0f);
animator->setDuration(1000);
animator->addListener(this);
animator->addUpdateListener(this);
animator->start(pTimelineHandler);

使用监听器

// 实现动画监听器
class MyAnimatorListener : public IAnimatorListener
{
public:
    STDMETHOD_(void, onAnimationStart)(THIS_ IValueAnimator *pAnimator) override
    {
        // 动画开始时的处理
    }

    STDMETHOD_(void, onAnimationEnd)(THIS_ IValueAnimator *pAnimator) override
    {
        // 动画结束时的处理
    }

    STDMETHOD_(void, onAnimationRepeat)(THIS_ IValueAnimator *pAnimator) override
    {
        // 动画重复时的处理
    }
};

// 创建动画并添加监听器
SValueAnimator* animator = new SFloatAnimator();
animator->setRange(0.0f, 1.0f);
animator->setDuration(1000);
animator->addListener(new MyAnimatorListener());
animator->start(pTimelineHandler);

最佳实践

  1. 合理设置动画时长:过短的动画会让用户感觉突兀,过长则会影响用户体验
  2. 选择合适的插值器:根据动画语义选择合适的插值器,比如弹出效果可以用弹跳插值器
  3. 避免过度动画:过多的动画会影响性能和用户体验
  4. 及时释放资源:动画结束后及时释放相关资源
  5. 处理动画中断:考虑动画被中断的情况,确保界面状态正确

总结

SValueAnimator 是 SOUI 动画系统的基础,它提供了一个简单但功能强大的时间引擎,用于运行动画并计算动画值。通过继承和扩展 SValueAnimator,可以实现各种复杂的动画效果。开发者可以使用它来创建基础的数值动画,或基于它构建更高级的动画功能。