2025-08-10 16:00:02 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 缓动函数集合
|
2025-11-02 23:50:41 +08:00
|
|
|
|
*
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 提供各种常用的缓动函数,用于创建平滑的动画效果
|
|
|
|
|
|
* 所有函数接受时间参数 t (0-1),返回缓动后的值 (通常0-1)
|
|
|
|
|
|
*/
|
|
|
|
|
|
export class Easing {
|
2025-11-02 23:50:41 +08:00
|
|
|
|
|
|
|
|
|
|
// 线性缓动
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 线性缓动(无缓动)
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static linear(t: number): number {
|
|
|
|
|
|
return t;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
// 二次方缓动 (Quadratic)
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 二次方缓入
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static quadIn(t: number): number {
|
|
|
|
|
|
return t * t;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 二次方缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static quadOut(t: number): number {
|
|
|
|
|
|
return 1 - (1 - t) * (1 - t);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 二次方缓入缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static quadInOut(t: number): number {
|
|
|
|
|
|
return t < 0.5 ? 2 * t * t : 1 - 2 * (1 - t) * (1 - t);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
// 三次方缓动 (Cubic)
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 三次方缓入
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static cubicIn(t: number): number {
|
|
|
|
|
|
return t * t * t;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 三次方缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static cubicOut(t: number): number {
|
|
|
|
|
|
return 1 - Math.pow(1 - t, 3);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 三次方缓入缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static cubicInOut(t: number): number {
|
|
|
|
|
|
return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
// 四次方缓动 (Quartic)
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 四次方缓入
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static quartIn(t: number): number {
|
|
|
|
|
|
return t * t * t * t;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 四次方缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static quartOut(t: number): number {
|
|
|
|
|
|
return 1 - Math.pow(1 - t, 4);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 四次方缓入缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static quartInOut(t: number): number {
|
|
|
|
|
|
return t < 0.5 ? 8 * t * t * t * t : 1 - Math.pow(-2 * t + 2, 4) / 2;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
// 五次方缓动 (Quintic)
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 五次方缓入
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static quintIn(t: number): number {
|
|
|
|
|
|
return t * t * t * t * t;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 五次方缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static quintOut(t: number): number {
|
|
|
|
|
|
return 1 - Math.pow(1 - t, 5);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 五次方缓入缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static quintInOut(t: number): number {
|
|
|
|
|
|
return t < 0.5 ? 16 * t * t * t * t * t : 1 - Math.pow(-2 * t + 2, 5) / 2;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
// 正弦缓动 (Sine)
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 正弦缓入
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static sineIn(t: number): number {
|
|
|
|
|
|
return 1 - Math.cos((t * Math.PI) / 2);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 正弦缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static sineOut(t: number): number {
|
|
|
|
|
|
return Math.sin((t * Math.PI) / 2);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 正弦缓入缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static sineInOut(t: number): number {
|
|
|
|
|
|
return -(Math.cos(Math.PI * t) - 1) / 2;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
// 指数缓动 (Exponential)
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 指数缓入
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static expoIn(t: number): number {
|
|
|
|
|
|
return t === 0 ? 0 : Math.pow(2, 10 * (t - 1));
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 指数缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static expoOut(t: number): number {
|
|
|
|
|
|
return t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 指数缓入缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static expoInOut(t: number): number {
|
|
|
|
|
|
if (t === 0) return 0;
|
|
|
|
|
|
if (t === 1) return 1;
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
return t < 0.5
|
|
|
|
|
|
? Math.pow(2, 20 * t - 10) / 2
|
|
|
|
|
|
: (2 - Math.pow(2, -20 * t + 10)) / 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 圆形缓动 (Circular)
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 圆形缓入
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static circIn(t: number): number {
|
|
|
|
|
|
return 1 - Math.sqrt(1 - t * t);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 圆形缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static circOut(t: number): number {
|
|
|
|
|
|
return Math.sqrt(1 - (t - 1) * (t - 1));
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 圆形缓入缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static circInOut(t: number): number {
|
|
|
|
|
|
return t < 0.5
|
|
|
|
|
|
? (1 - Math.sqrt(1 - 4 * t * t)) / 2
|
|
|
|
|
|
: (Math.sqrt(1 - (-2 * t + 2) * (-2 * t + 2)) + 1) / 2;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
// 回弹缓动 (Back)
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 回弹缓入
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @param s 回弹强度,默认1.70158
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static backIn(t: number, s: number = 1.70158): number {
|
|
|
|
|
|
const c1 = s;
|
|
|
|
|
|
const c3 = c1 + 1;
|
|
|
|
|
|
return c3 * t * t * t - c1 * t * t;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 回弹缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @param s 回弹强度,默认1.70158
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static backOut(t: number, s: number = 1.70158): number {
|
|
|
|
|
|
const c1 = s;
|
|
|
|
|
|
const c3 = c1 + 1;
|
|
|
|
|
|
return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 回弹缓入缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @param s 回弹强度,默认1.70158
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static backInOut(t: number, s: number = 1.70158): number {
|
|
|
|
|
|
const c1 = s;
|
|
|
|
|
|
const c2 = c1 * 1.525;
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
return t < 0.5
|
|
|
|
|
|
? (Math.pow(2 * t, 2) * ((c2 + 1) * 2 * t - c2)) / 2
|
|
|
|
|
|
: (Math.pow(2 * t - 2, 2) * ((c2 + 1) * (t * 2 - 2) + c2) + 2) / 2;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
// 弹性缓动 (Elastic)
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 弹性缓入
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @param amplitude 振幅,默认1
|
|
|
|
|
|
* @param period 周期,默认0.3
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static elasticIn(t: number, amplitude: number = 1, period: number = 0.3): number {
|
|
|
|
|
|
if (t === 0) return 0;
|
|
|
|
|
|
if (t === 1) return 1;
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
const s = period / 4;
|
|
|
|
|
|
return -(amplitude * Math.pow(2, 10 * (t - 1)) * Math.sin((t - 1 - s) * (2 * Math.PI) / period));
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 弹性缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @param amplitude 振幅,默认1
|
|
|
|
|
|
* @param period 周期,默认0.3
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static elasticOut(t: number, amplitude: number = 1, period: number = 0.3): number {
|
|
|
|
|
|
if (t === 0) return 0;
|
|
|
|
|
|
if (t === 1) return 1;
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
const s = period / 4;
|
|
|
|
|
|
return amplitude * Math.pow(2, -10 * t) * Math.sin((t - s) * (2 * Math.PI) / period) + 1;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 弹性缓入缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @param amplitude 振幅,默认1
|
|
|
|
|
|
* @param period 周期,默认0.45
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static elasticInOut(t: number, amplitude: number = 1, period: number = 0.45): number {
|
|
|
|
|
|
if (t === 0) return 0;
|
|
|
|
|
|
if (t === 1) return 1;
|
|
|
|
|
|
|
|
|
|
|
|
const s = period / 4;
|
|
|
|
|
|
|
|
|
|
|
|
if (t < 0.5) {
|
|
|
|
|
|
return -0.5 * (amplitude * Math.pow(2, 10 * (2 * t - 1)) * Math.sin((2 * t - 1 - s) * (2 * Math.PI) / period));
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
return amplitude * Math.pow(2, -10 * (2 * t - 1)) * Math.sin((2 * t - 1 - s) * (2 * Math.PI) / period) * 0.5 + 1;
|
2025-08-10 16:00:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
// 跳跃缓动 (Bounce)
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 跳跃缓入
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static bounceIn(t: number): number {
|
|
|
|
|
|
return 1 - Easing.bounceOut(1 - t);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 跳跃缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static bounceOut(t: number): number {
|
|
|
|
|
|
const n1 = 7.5625;
|
|
|
|
|
|
const d1 = 2.75;
|
|
|
|
|
|
|
|
|
|
|
|
if (t < 1 / d1) {
|
|
|
|
|
|
return n1 * t * t;
|
|
|
|
|
|
} else if (t < 2 / d1) {
|
|
|
|
|
|
return n1 * (t -= 1.5 / d1) * t + 0.75;
|
|
|
|
|
|
} else if (t < 2.5 / d1) {
|
|
|
|
|
|
return n1 * (t -= 2.25 / d1) * t + 0.9375;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return n1 * (t -= 2.625 / d1) * t + 0.984375;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 跳跃缓入缓出
|
|
|
|
|
|
* @param t 时间参数 (0-1)
|
|
|
|
|
|
* @returns 缓动值
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static bounceInOut(t: number): number {
|
|
|
|
|
|
return t < 0.5
|
|
|
|
|
|
? (1 - Easing.bounceOut(1 - 2 * t)) / 2
|
|
|
|
|
|
: (1 + Easing.bounceOut(2 * t - 1)) / 2;
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
// 组合缓动
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 创建自定义缓动函数(组合多个缓动)
|
|
|
|
|
|
* @param easingFunctions 缓动函数数组
|
|
|
|
|
|
* @param weights 权重数组,默认均等
|
|
|
|
|
|
* @returns 组合后的缓动函数
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static combine(
|
|
|
|
|
|
easingFunctions: ((t: number) => number)[],
|
|
|
|
|
|
weights?: number[]
|
|
|
|
|
|
): (t: number) => number {
|
|
|
|
|
|
if (!weights) {
|
|
|
|
|
|
weights = new Array(easingFunctions.length).fill(1 / easingFunctions.length);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
return (t: number): number => {
|
|
|
|
|
|
let result = 0;
|
|
|
|
|
|
for (let i = 0; i < easingFunctions.length; i++) {
|
|
|
|
|
|
result += easingFunctions[i](t) * (weights![i] || 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 创建分段缓动函数
|
|
|
|
|
|
* @param segments 分段配置数组,每段包含 {duration, easing}
|
|
|
|
|
|
* @returns 分段缓动函数
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static piecewise(segments: Array<{duration: number; easing: (t: number) => number}>): (t: number) => number {
|
2025-08-10 16:00:02 +08:00
|
|
|
|
// 计算总持续时间
|
2025-11-02 23:50:41 +08:00
|
|
|
|
const totalDuration = segments.reduce((sum, seg) => sum + seg.duration, 0);
|
|
|
|
|
|
|
|
|
|
|
|
// 归一化持续时间
|
|
|
|
|
|
const normalizedSegments = segments.map((seg) => ({
|
|
|
|
|
|
...seg,
|
|
|
|
|
|
duration: seg.duration / totalDuration
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
return (t: number): number => {
|
|
|
|
|
|
let accumulatedTime = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (const segment of normalizedSegments) {
|
|
|
|
|
|
if (t <= accumulatedTime + segment.duration) {
|
|
|
|
|
|
const localT = (t - accumulatedTime) / segment.duration;
|
|
|
|
|
|
return segment.easing(Math.max(0, Math.min(1, localT)));
|
|
|
|
|
|
}
|
|
|
|
|
|
accumulatedTime += segment.duration;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果超出范围,返回最后一段的结束值
|
|
|
|
|
|
return normalizedSegments[normalizedSegments.length - 1].easing(1);
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 创建反向缓动函数
|
|
|
|
|
|
* @param easing 原缓动函数
|
|
|
|
|
|
* @returns 反向缓动函数
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static reverse(easing: (t: number) => number): (t: number) => number {
|
|
|
|
|
|
return (t: number): number => 1 - easing(1 - t);
|
|
|
|
|
|
}
|
2025-08-10 16:00:02 +08:00
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
|
/**
|
2025-08-10 16:00:02 +08:00
|
|
|
|
* 创建镜像缓动函数(先正向再反向)
|
|
|
|
|
|
* @param easing 原缓动函数
|
|
|
|
|
|
* @returns 镜像缓动函数
|
|
|
|
|
|
*/
|
2025-11-02 23:50:41 +08:00
|
|
|
|
static mirror(easing: (t: number) => number): (t: number) => number {
|
|
|
|
|
|
return (t: number): number => {
|
|
|
|
|
|
if (t < 0.5) {
|
|
|
|
|
|
return easing(t * 2);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return easing(2 - t * 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 常用预设
|
|
|
|
|
|
|
|
|
|
|
|
/** 平滑进入(常用于UI动画) */
|
|
|
|
|
|
static readonly smoothIn = Easing.quadOut;
|
|
|
|
|
|
|
|
|
|
|
|
/** 平滑退出(常用于UI动画) */
|
|
|
|
|
|
static readonly smoothOut = Easing.quadIn;
|
|
|
|
|
|
|
|
|
|
|
|
/** 快速进入(常用于出现动画) */
|
|
|
|
|
|
static readonly quickIn = Easing.cubicOut;
|
|
|
|
|
|
|
|
|
|
|
|
/** 快速退出(常用于消失动画) */
|
|
|
|
|
|
static readonly quickOut = Easing.cubicIn;
|
|
|
|
|
|
|
|
|
|
|
|
/** 自然运动(模拟物理) */
|
|
|
|
|
|
static readonly natural = Easing.quartOut;
|
|
|
|
|
|
|
|
|
|
|
|
/** 强调效果(吸引注意力) */
|
|
|
|
|
|
static readonly emphasize = Easing.backOut;
|
|
|
|
|
|
}
|