单纯用translateY线性变化无法模拟真实弹跳,因其缺少重力加速、触底压缩、回弹衰减等物理特征;需通过4关键帧+分段cubic-bezier+transform-origin等细节协同实现。

为什么单纯用 translateY 做不出真实弹跳感
直接线性改变 translateY 值(比如从 0 到 -100px 再回 0)只会产生匀速上下运动,缺少重力加速、触底压缩、回弹衰减这些物理特征。真实弹跳的关键在于:触底前加速、触底瞬间有短暂“压扁”停顿、回弹时先快后慢、多次振幅递减。
用 @keyframes 模拟弹跳的 4 个关键帧节点
一个基础但有效的弹跳动画至少需要 4 个关键帧来刻画节奏:
-
0%:起始位置(translateY(0)),准备下落 -
60%:触底最低点(如translateY(80px)),并加轻微缩放模拟压缩(scaleY(0.9)) -
75%:第一次回弹高点(translateY(-20px)),速度开始变慢 -
100%:回到原位(translateY(0)),可加轻微过冲再回调增强弹性感(如先到translateY(-5px)再回 0)
注意:时间比例不是均分的——触底和回弹初期要快,末段要拖一点,否则像弹簧而非弹球。
animation-timing-function 必须用 cubic-bezier
默认的 ease 或 linear 都撑不起弹跳。推荐两个常用贝塞尔曲线:
立即学习“前端免费学习笔记(深入)”;
- 主弹跳阶段(0% → 60% → 75%):用
cubic-bezier(0.22, 0.61, 0.36, 1)模拟加速下落+快速回弹 - 收尾阶段(75% → 100%):换
cubic-bezier(0.76, 0.25, 0.65, 0.95)让最后回位带点惯性过冲
不要给整个动画统一设一个 timing-function,而是拆成多段 animation 或用 @keyframes 内联 animation-timing-function(需配合 animation-fill-mode: forwards 和分段延迟)。
实际使用时容易忽略的 3 个细节
弹跳动画上线后常显得“飘”或“卡”,多半栽在这几点:
- 没关掉默认的
transform-origin:确保是transform-origin: center,否则缩放会偏移中心 - 父容器没设
overflow: hidden:弹跳时元素可能短暂超出容器,尤其用scaleY压缩时视觉错位 - 没考虑多次触发冲突:如果用户快速连续点击触发动画,要用
animation-play-state: paused或 JS 控制animation-name切换,避免动画队列堆积
真正自然的弹跳不是堆参数,而是把“触底压缩→能量释放→余震衰减”这三步节奏感做出来;调参时盯着预览动效比看数值重要得多。










