2. 缓动曲线:EasingEquations详解、自定义缓动曲线、缓动曲线选择策略
缓动曲线这东西,说白了就是让动画“活”起来的灵魂。没有它,你的UI动效就像机器人走路——生硬、死板。我在做第一个TouchGFX项目时,就因为偷懒全用了线性动画,结果被产品经理打回来重做了三次。嗯,从那以后我花了不少时间研究缓动曲线,今天就把这些经验分享给你。
2.1 缓动曲线到底是什么?
先看一个直观的例子。假设你要把一个按钮从屏幕左边移到右边:
- 线性运动:按钮全程匀速移动,像传送带上的包裹,毫无生气。
- 缓入缓出:按钮先加速、再减速,像真实世界里的物体运动,自然流畅。
缓动曲线就是描述这种“速度变化规律”的数学函数。TouchGFX内置了30多种标准缓动方程,覆盖了绝大多数场景。
核心概念:缓动曲线本质上是一个数学函数 f(t),输入时间 t(0→1),输出进度 p(0→1)。线性曲线的 f(t)=t,而缓入曲线的 f(t)=t²,速度从慢到快。
2.2 EasingEquations 详解
TouchGFX的缓动方程都定义在 EasingEquations 类中。我习惯把它们分成四大家族:
| 家族 | 代表方程 | 运动特征 | 适用场景 |
|---|---|---|---|
| 缓入 (In) | QuadIn, CubicIn, ExpoIn | 开始慢,结束快 | 物体离开屏幕、弹出菜单收起 |
| 缓出 (Out) | QuadOut, CubicOut, ExpoOut | 开始快,结束慢 | 物体进入屏幕、弹窗出现 |
| 缓入缓出 (InOut) | QuadInOut, SineInOut | 两头慢,中间快 | 页面切换、卡片翻转 |
| 弹性/回弹 | ElasticInOut, BounceOut | 超出目标再回弹 | 通知提示、点赞动画 |
代码里怎么用?很简单:
// 创建一个缓入缓出的移动动画
MoveAnimator<Image> animator(image);
animator.setMoveAnimationEndedCallback(callback);
animator.startMove(100, 200, 300, EasingEquations::CubicEaseInOut);
我个人最常用的是 CubicEaseInOut——它比Quad更柔和,又不像Expo那么夸张。你想想看,大部分UI动效其实不需要太强的存在感,Cubic刚刚好。
小技巧:如果你不确定选哪个,先用 SineEaseInOut 试试。它的曲线最平滑,几乎不会出错。我在原型阶段经常用这个占位。
2.3 自定义缓动曲线
内置方程虽然多,但总有不够用的时候。我记得有一次做“水滴下落”的动效,内置的Bounce曲线太规则了,完全不像真实的水滴。这时候就需要自定义了。
TouchGFX支持两种自定义方式:
方式一:继承 EasingEquation 基类
class MyCustomEasing : public EasingEquation {
public:
virtual float ease(float t) const override {
// 自定义缓动函数:先快后慢再快
if (t < 0.5f) {
return 2.0f * t * t; // 前半段加速
} else {
return 1.0f - 2.0f * (1.0f - t) * (1.0f - t); // 后半段减速
}
}
};
// 使用
MyCustomEasing myEasing;
animator.startMove(100, 200, 300, myEasing);
方式二:使用贝塞尔曲线
如果你熟悉CSS的cubic-bezier,TouchGFX也支持类似的方式:
// 定义控制点 (x1, y1, x2, y2)
// 这里模拟一个"先弹跳再平稳"的效果
CubicBezierEasing bezier(0.25f, 1.5f, 0.5f, 1.0f);
animator.startMove(100, 200, 300, bezier);
注意:自定义缓动函数时,一定要保证 ease(0)=0 且 ease(1)=1。我曾经犯过这个错,结果动画跑到一半突然跳回起点,排查了半天才发现是函数没归一化。
2.4 缓动曲线选择策略
选缓动曲线不是拍脑袋的事。我总结了一套“三看”原则:
- 看运动方向:进入用Out,离开用In,来回用InOut。
- 看运动距离:短距离(<50px)用Quad,中距离用Cubic,长距离用Expo。
- 看交互反馈:按钮点击用BackOut(轻微过冲),页面切换用QuintInOut(平滑过渡)。
下面这张SVG图帮你快速定位:
2.5 实战中的避坑指南
最后聊几个我踩过的坑:
- 别用Elastic做核心交互:弹性动画看起来很酷,但用户等不起。我曾经在登录按钮上用了ElasticInOut,结果用户反馈“按钮弹了半天才反应过来”。
- 注意动画时长匹配:缓入缓出动画如果时长太短(<150ms),效果几乎看不出来。我一般把InOut动画设在300-500ms之间。
- 小心Expo的“急刹车”:ExpoEaseOut在结尾处变化极快,如果动画目标值很大,会出现“突然停住”的视觉断层。这时候换成Cubic更稳妥。
我的调试习惯:在TouchGFX Designer里,我会先用Slider控件手动拖拽测试不同缓动曲线的效果。等视觉上满意了,再固化到代码里。这样比反复编译快得多。