物理手感

手指抬起后会发生什么?后续的一切运动,都由物理系统接管 — 动量、摩擦、弹簧、弹性边界。正是这些看不见的力, 让手势驱动的界面显得自然而鲜活。

·····

Part A · 抬手后阶段

抬手之后

手指离开屏幕的瞬间,速度不会凭空消失 — 它传递给了内容。 理解动量、摩擦与衰减预测,是打造"物理上可信"的交互手感的基础。

·····

Momentum(动量)

你甩动手机里的列表时,列表不会在抬手瞬间戛然而止, 而是继续滑行,仿佛带着惯性。这就是 momentum scrolling — 释放瞬间采样到的速度,被完整地带入了后续运动。

没有动量,每次滚动都像在泥里拖行。加入动量后, 一次轻快的 flick 就能把内容送到更符合预期的位置。

Momentum:手指抬起后速度仍会继续演化
fig-200 · momentum scroll
上下拖动
·····

Friction(摩擦)

动量不会无限持续。摩擦让内容逐步减速,直至停下。 摩擦系数,是滚动手感中最重要的调参旋钮之一。

iOS 和 Android 的摩擦参数并不相同 — 这也是同样的甩动动作 在不同平台手感迥异的原因之一。摩擦太小会"打滑",太大则"发粘"。

用下面这个滑块直接感受差异:

·····

Decay(衰减)

动量给出了初始速度,接下来呢?速度不会瞬间归零, 而是沿着指数曲线衰减:前段减速猛烈,后段渐趋平缓。

这种形状正是"自然减速感"的来源。线性减速像匀速刹车,显得机械; 指数衰减更像真实摩擦 — 速度越低,阻力的效果越微弱。

试着甩动下方圆点,观察 ghost 标记:它们在时间上等间隔, 在空间上却不等间隔。起始处间距大、末尾处间距密 — 这正是衰减曲线的可视化写照。

fig-201 · exponential decay
甩动圆点
·····

Part B · 弹簧阶段

弹簧

弹簧是响应式动画的根基。与固定时长的动画不同, 弹簧可以在任意时刻被打断并平滑续接 — 界面因此显得流动,而非僵硬。

·····

为什么用弹簧?

你下拉一个面板然后松手,它弹了回去。这个"弹回"不是预设的定时动画, 而是实时模拟出来的弹簧过程。这一区别至关重要。

“用时长和缓动曲线参数化的动画 API, 在底层上与连续、流体的交互是冲突的。”
Andy Matuschak,前 Apple UIKit 团队

传统 CSS 动画由 时长 + 缓动曲线定义 (例如 transition: 0.3s ease-in-out)。 这种方式有一个硬伤:动画难以优雅地被中断。若用户在动画途中再次触摸, 系统通常只能"跳到终点"或"从头重来" — 两者都不自然。

弹簧之所以更适合交互,因为它基于状态,而非基于时间。 弹簧随时知道自己的位置和速度;任意时刻都能改变目标,它会在保留动量的前提下 平滑转向。弹簧没有固定"总时长" — 何时稳定,由物理状态决定。

弹簧性格

一条弹簧的“性格”主要由 stiffness(刚度)damping(阻尼)决定:

手感参数特征适用场景
弹跳高刚度、低阻尼趣味交互、开关、徽章
利落中等刚度、接近临界阻尼抽屉关闭、导航过渡、主流 UI
厚重较低刚度、过阻尼模态层、重要状态切换
Spring:刚度与阻尼决定运动性格
fig-202 · spring physics
拖动盒子
·····

Elastic(弹性)

Elastic 可以理解为"过冲更加夸张的弹簧"。普通弹簧会相对平稳地靠近目标; Elastic 则故意越过目标,并做可见的振荡,像橡皮筋回弹。

这种效果一般通过降低阻尼(让振荡持续更久)、同时保持较高刚度来获得。 结果是更跳跃、更抓眼球的动态表现。

Elastic 适合少量、点睛式使用,典型场景包括:

  • 庆祝时刻 — 徽章、成就、成功确认
  • 吸引注意 — 需立即处理的通知或错误
  • 玩味 UI — 开关、反应、表情交互

切忌将 Elastic 用在高频动作上 — 过度弹跳在高重复场景中会迅速造成视觉疲劳。

fig-202b · elastic spring
任意位置点击
·····

Fling & Snap(甩动与吸附)

很多界面在抬手后,需要将位置量化到离散值。 轮播吸附到整页、抽屉吸附到开/关状态、选择器吸附到离散选项 — 都是典型场景。

常见模式是:释放时先用指数衰减预测内容的自然停点 — target = pos + v / (1 − decayRate), 然后将预测结果四舍五入到最近合法吸附点,再用 临界阻尼弹簧ζ = 1.0)驱动到目标。 fling 速度注入弹簧初速度,确保过渡连续 — 不跳变、不停顿。甩得快则预测更远,可能跨项;甩得慢则倾向就近吸附。

Decay-targeted snap:同一位置、不同速度 → 不同预测目标
fig-203 · discrete picker
滚动选择
·····

Part C · 边界阶段

边界行为

到达边缘时该怎么办?硬停像撞墙。弹性边界则能在表达"已到极限"的同时, 维持连续物理世界的错觉。

·····

Rubber Band / Overscroll(橡皮筋 / 超滚动)

当你把内容拖过可滚动区域的边界,该发生什么? 直接停死会像撞墙。多数平台采用 rubber band 效果: 内容继续跟手,但阻力越来越大,像在拉伸一根弹性带。

关键在于:越界后"手指位移 → 视觉位移"的映射变成了 非线性。你越往外拖,每像素手指移动所带来的内容位移就越小。

这本质上是一种信息传达机制:递增的阻力在告诉用户 "你已经到边界了" — 比硬停更温和,也更合乎直觉。

Rubber band:越过边界后阻力持续增大
fig-204 · rubber band
拖过 0 或 60
·····

Bounce-Back(回弹)

Bounce-back 是 rubber band 的收尾机制。Rubber band 管的是越界拖动过程中的行为; Bounce-back 管的是越界状态在释放之后如何收敛。

手指抬起时,若内容仍在越界区间,弹簧会将它拉回最近合法边界。 这个衔接必须连续:弹簧的起点应取 rubber-banded 后的显示位置,而非原始手指位置 — 否则拖动结束到回弹开始的瞬间会出现视觉跳变。

Rubber band + bounce-back,共同构成了你在 iOS 滚动末端常感受到的"弹性吸附"。 它像物理,而不像写死的逻辑 — 这正是好的边界行为该有的样子。

fig-205 · overscroll bounce
甩到边界外
·····

综合起来看

本章的这些机制会协同运作,形成流畅而即时的交互体验:

  • Momentum — 释放时继承速度
  • Friction — 持续减速
  • Decay — 指数减速与目标预测
  • Springs — 可中断、状态驱动动画
  • Fling & snap — 基于衰减预测,再用临界阻尼弹簧吸附到最近目标
  • Rubber band — 边界处的弹性阻力
  • Bounce-back — 越界后的弹簧回归

下一章,我们将看到这些原语如何组合成 交互模式 — 下拉刷新、轮播、可重排网格、橡皮筋滑杆。