先记住这个答案
自定义速度曲线使用 cubic-bezier() 函数,接受四个参数表示两个控制点 (x1, y1, x2, y2)。曲线的输入是时间从 0 到 1,输出是进度从 0 到 1,控制点的 y 值可超出 [0,1] 以产生回弹效果;但 x 必须在 [0,1] 内以保持时间单调性,y 没有硬性限制,但过大的偏移可能导致进度越界并被实际属性值域截断。
cubic-bezier有 2 个控制点共 4 参数- x 坐标必须在 0~1 之间
- y 坐标可超出 0~1 产生回弹
贝塞尔曲线参数如何映射速度
cubic-bezier(x1,y1,x2,y2) 定义一条从 (0,0) 到 (1,1) 的三次贝塞尔曲线,其中 (x1,y1) 和 (x2,y2) 是两个控制点。动画时间从 0→1 映射到进度 0→1,曲线横轴是时间百分比,纵轴是属性完成度。曲线越陡,表示该时段进度变化快,即速度快。
x 坐标决定控制点沿时间轴的位置,x 超出 [0,1] 会使函数无效,时间映射失去单调性,因此 x 必须在区间内。y 值则代表“控制点在该时刻的速度倾向”,y>1 或 y<0 会使曲线在终点前超过最终值或低于初始值,形成回弹/过冲效果。四个参数即两个控制点共四个数值,不可增减。
制作有轻微回弹的弹跳按钮
一个弹跳按钮要求落下时超出目标略有回弹。需求:从 0 到 100% 移动,希望先快后慢,到终点前超过 100% 再回落到 100%?实际要过冲。输入:transition: transform 0.5s,使用 cubic-bezier(0.5, 1.5, 0.5, 1)。这里有 y1=1.5>1,使得曲线向上凸起,在接近终点时超过 1(即超出目标),随后回落。
为何这样选?四个参数中,x1=0.5、x2=0.5 表示两个控制点时间都在中间,y1=1.5 使开始阶段进度上升较快并有过冲,y2=1 则稳定在终点。结果运动有轻微回弹但不发生反向,因为 y2 不过低。若 y 设置过大如 4,会强烈过冲造成抖动,因此要小范围超出。
容易失效的边界条件
如果 x 坐标超出 [0,1],该 transition-timing-function 声明无效,属性将使用初始值 ease。因此写 cubic-bezier(1.2, 0, 0.8, 1) 无效。另外如果 y 值很大造成过冲,但属性本身有值域限制(如 opacity 在 0 到 1 之间),计算值会被 clamp,因此视觉上不会出现负值,但超出部分被截断,过冲效果可能不可见。
处理方式:对不可插值的属性(如 display)或非数值属性无法使用任何 easing,对会超出范围的属性值,浏览器仅 clamp 到实际值域,如 opacity 到 [0,1]。需要过冲效果时尽量用于 transform 等可平滑越界属性,并测试合适的 y 范围,避免动画突兀。
容易答错的地方
- 认为 y 坐标也必须在 0 到 1
- 实际 y 可以小于 0 或大于 1,正是可以形成回弹或过冲的关键。x 由于必须保证时间映射单调才限定在 [0,1],y 并无此限制。
- 把 cubic-bezier 理解为四个关键点
- 它只有四个参数对应两个控制点的坐标,不是四个点。曲线始终有两个固定端点 (0,0) 和 (1,1),控制点只决定弯曲形状。
面试官还会怎么问?
ease 关键字与 cubic-bezier 如何对应?
ease 等价于 cubic-bezier(0.25, 0.1, 0.25, 1),其他如 ease-in 对应 (0.42,0,1,1),可互换使用。掌握关键字可快速开发。
cubic-bezier 能实现 steps 的阶梯效果吗?
不能,cubic-bezier 是连续曲线,无法产生间断跳跃;阶梯效果需使用 steps(),它与贝塞尔不同。
如何调试曲线效果?
可使用浏览器开发者工具实时调整,或通过 cubic-bezier.com 可视化参考。调试时关注过冲幅度与末端速度。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。