SOUI 数值动画 (ValueAnimator)¶
概述¶
SOUI 数值动画(SValueAnimator)是 SOUI 动画系统的基础类,提供了一个简单的时间引擎来运行动画并计算动画值。它是整个动画系统的核心,为其他动画类型(如属性动画和动画集合)提供基础功能。
SValueAnimator 本身不直接操作任何控件属性,而是通过计算随时间变化的数值,并在动画过程中通知监听器,从而实现各种动画效果。
核心概念¶
动画生命周期¶
数值动画具有明确的状态转换过程:
- idle(空闲):动画创建后的初始状态
- started(已启动):调用 start() 方法后进入此状态
- running(运行中):动画真正开始执行时的状态
- 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);
最佳实践¶
- 合理设置动画时长:过短的动画会让用户感觉突兀,过长则会影响用户体验
- 选择合适的插值器:根据动画语义选择合适的插值器,比如弹出效果可以用弹跳插值器
- 避免过度动画:过多的动画会影响性能和用户体验
- 及时释放资源:动画结束后及时释放相关资源
- 处理动画中断:考虑动画被中断的情况,确保界面状态正确
总结¶
SValueAnimator 是 SOUI 动画系统的基础,它提供了一个简单但功能强大的时间引擎,用于运行动画并计算动画值。通过继承和扩展 SValueAnimator,可以实现各种复杂的动画效果。开发者可以使用它来创建基础的数值动画,或基于它构建更高级的动画功能。