跳到主要内容

缓动函数 (easing)

基于三次贝塞尔曲线的缓动动画模块,通过定义曲线控制点实现各种加减速效果。

贝塞尔曲线

struct bezier_t {
float ax, bx, cx; /* X 分量的三次多项式系数 */
float ay, by, cy; /* Y 分量的三次多项式系数 */
};

标准三次贝塞尔曲线由 4 个控制点定义:P0=(0,0)、P1=(x1,y1)、P2=(x2,y2)、P3=(1,1)。bezier_init 将控制点转换为多项式系数,bezier_calc 通过牛顿迭代法 + 二分法求值。

void bezier_init(struct bezier_t * b, float x1, float y1, float x2, float y2);

初始化贝塞尔曲线,x1/y1x2/y2 为中间两个控制点,取值范围 [0, 1]。

float bezier_calc(struct bezier_t * b, float t);

计算时间 t(0~1)对应的曲线值。t <= 0 返回 0,t >= 1 返回 1。

缓动动画

struct easing_t {
struct bezier_t bezier; /* 贝塞尔曲线 */
float start; /* 起始值 */
float stop; /* 终止值 */
float duration; /* 持续时间(秒) */
float acc; /* 累计时间 */
};

API

void easing_init(struct easing_t * e, float start, float stop, float duration, float x1, float y1, float x2, float y2);

初始化缓动动画。start/stop 为数值范围,duration 为总时长,x1/y1/x2/y2 为贝塞尔控制点。

float easing_calc(struct easing_t * e, float t);

计算时刻 t(秒)对应的值。

float easing_step(struct easing_t * e, float dt);

推进 dt 秒并返回当前值。内部累计时间自动累加。

int easing_finished(struct easing_t * e);

动画是否结束,结束返回 1。

常用曲线参数

效果x1y1x2y2
线性0011
缓入0.42011
缓出000.581
缓入缓出0.4200.581
弹性缓出0.68-0.550.271.55

使用示例

位移动画

struct easing_t e;
easing_init(&e, 0, 300, 0.5, 0.42, 0, 0.58, 1); /* 缓入缓出,0→300,0.5秒 */

while(!easing_finished(&e))
{
float pos = easing_step(&e, 0.016); /* 每帧约16ms */
set_position(pos);
}

直接计算指定时刻

struct easing_t e;
easing_init(&e, 0, 100, 1.0, 0, 0, 0.58, 1);
float v = easing_calc(&e, 0.5); /* 0.5秒时的值 */

单独使用贝塞尔曲线

struct bezier_t b;
bezier_init(&b, 0.42, 0, 0.58, 1);
float progress = bezier_calc(&b, 0.5); /* 进度50%时的曲线值 */