You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
40 lines
1.2 KiB
40 lines
1.2 KiB
/** 行业常用缓动曲线(Duolingo / Material / 手游 Modal 规范) */
|
|
|
|
/** 入场:cubic-bezier(0, 0, 0.2, 1) — 快启慢收 */
|
|
export function easeEnter(t: number): number {
|
|
return cubicBezierY(t, 0, 0, 0.2, 1);
|
|
}
|
|
|
|
/** 退场:cubic-bezier(0.4, 0, 1, 1) — 快出 */
|
|
export function easeExit(t: number): number {
|
|
return cubicBezierY(t, 0.4, 0, 1, 1);
|
|
}
|
|
|
|
/** 庆祝 overshoot:cubic-bezier(0.34, 1.56, 0.64, 1) — Duolingo 奖励弹入 */
|
|
export function easeCelebrate(t: number): number {
|
|
return cubicBezierY(t, 0.34, 1.56, 0.64, 1);
|
|
}
|
|
|
|
/** 标准双向往返:cubic-bezier(0.4, 0, 0.2, 1) */
|
|
export function easeStandard(t: number): number {
|
|
return cubicBezierY(t, 0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
function cubicBezierY(t: number, x1: number, y1: number, x2: number, y2: number): number {
|
|
if (t <= 0) return 0;
|
|
if (t >= 1) return 1;
|
|
let lo = 0;
|
|
let hi = 1;
|
|
for (let i = 0; i < 10; i++) {
|
|
const mid = (lo + hi) * 0.5;
|
|
if (bezier(x1, x2, mid) < t) lo = mid;
|
|
else hi = mid;
|
|
}
|
|
const u = (lo + hi) * 0.5;
|
|
return bezier(y1, y2, u);
|
|
}
|
|
|
|
function bezier(a: number, b: number, t: number): number {
|
|
const inv = 1 - t;
|
|
return 3 * inv * inv * t * a + 3 * inv * t * t * b + t * t * t;
|
|
}
|
|
|