modern_ui_design

第七章:动效设计与时间美学

章节概述

动效设计是现代UI/UX中的第四维度——时间。本章将探讨如何通过精心编排的动画创造流畅、自然且富有意义的用户体验。我们将从音乐理论的节奏与和声中汲取灵感,深入研究贝塞尔曲线的数学原理,探讨物理动画的真实感,并掌握性能优化的技术要点。通过本章学习,你将理解动效不仅是装饰,而是传达状态变化、引导注意力、增强可用性的关键设计语言。

7.1 动效设计的基础原理

7.1.1 时间作为设计维度

在传统的视觉设计中,我们处理的是二维空间(x、y坐标)和深度(z轴)。动效设计引入了第四个维度:时间(t)。这个维度的加入让设计从静态转向动态,从瞬间转向过程。

空间位置: P(x, y, z)
时间函数: P(t) = (x(t), y(t), z(t))

时间维度带来了新的设计变量:

动效的本质是状态的连续变化:

时间感知的心理学基础:

短时感知: < 100ms - 几乎瞬时,用于即时反馈
快速感知: 100-300ms - 快速过渡,不打断思维流
中等感知: 300-1000ms - 明显的动画,用于重要转换
长时感知: > 1000ms - 需要等待,可能引起焦虑

7.1.2 动效的认知价值

从认知心理学角度,动效服务于以下目的:

  1. 连续性感知:人类视觉系统通过运动检测来理解对象的持续性
    • 对象恒常性:移动的物体被识别为同一对象
    • 视觉追踪:眼球运动跟随移动目标
    • 预测机制:大脑预测运动轨迹
  2. 因果关系:动画帮助用户理解操作与结果之间的联系
    • 直接操纵感:拖拽、滑动的即时响应
    • 反馈确认:按钮按下的视觉确认
    • 状态转换:加载、成功、失败的过程展示
  3. 空间导航:通过动画过渡保持用户的空间定位感
    • 心智地图:用户构建界面的空间模型
    • 导航面包屑:通过动画显示层级关系
    • 视图转换:平滑过渡减少认知断层
  4. 注意力引导:运动是最强的视觉刺激之一
    • 周边视觉:人眼对运动特别敏感
    • 优先级暗示:通过动画强调重要元素
    • 扫描路径:引导用户的视线流动
  5. 情感传达:动效能传递品牌个性和情感色彩
    • 活泼轻快:弹性、快速的动画
    • 优雅精致:缓慢、流畅的过渡
    • 科技感:精确、几何化的运动

7.1.3 动效的设计原则

1. 自然性原则

真实世界的运动遵循物理定律,用户对这些规律有直觉认知:

牛顿运动定律在UI中的体现:
- 惯性定律:静止物体保持静止,运动物体保持匀速直线运动
  UI应用:滚动列表的惯性滑动
  
- 加速度定律:F = ma,力产生加速度
  UI应用:拖拽的阻力感,重量感的模拟
  
- 作用反作用:每个作用力都有反作用力
  UI应用:弹性边界的回弹效果

自然运动的特征:

2. 目的性原则

每个动效都应有明确的功能,避免为动而动:

功能分类:

3. 性能原则

动效不应牺牲性能,流畅度直接影响用户体验:

性能指标:

帧率要求:
- 60 FPS (16.67ms/帧): 理想目标,丝滑体验
- 30 FPS (33.33ms/帧): 最低要求,可接受
- < 30 FPS: 明显卡顿,需要优化

渲染管线:
JavaScript → Style → Layout → Paint → Composite
   3ms        3ms      3ms      6ms       2ms = 17ms

优化策略:

4. 一致性原则

动效风格应该在整个产品中保持一致:

一致性维度:

建立动效规范:

动效设计令牌(Motion Tokens):
--duration-instant: 100ms
--duration-fast: 200ms
--duration-normal: 300ms
--duration-slow: 500ms

--easing-standard: cubic-bezier(0.4, 0, 0.2, 1)
--easing-decelerate: cubic-bezier(0, 0, 0.2, 1)
--easing-accelerate: cubic-bezier(0.4, 0, 1, 1)

5. 克制原则

过度的动效会分散注意力,甚至引起视觉疲劳:

克制策略:

判断标准:

必要动效:
✓ 提供操作反馈
✓ 显示状态变化
✓ 保持空间连续性

可选动效:
? 增强品牌感
? 提升愉悦度
? 展示加载过程

避免动效:
✗ 纯装饰用途
✗ 重复循环动画
✗ 影响内容阅读

7.2 缓动函数与时间曲线

7.2.1 线性与非线性运动

线性运动是最简单但也最不自然的动画形式:

线性函数: f(t) = t
位置公式: x(t) = x₀ + v·t
速度公式: v(t) = 常数
加速度: a(t) = 0
线性运动图示:
位置                速度               加速度
  ^                  ^                  ^
  |     /           |------            |
  |    /            |                  |------ (0)
  |   /             |                  |
  |  /              |                  |
  | /               |                  |
  |/_______>        |_______>          |_______>
      时间              时间               时间

线性运动的问题:

  1. 不自然:自然界中几乎没有纯线性运动
  2. 生硬:突然开始和停止,缺乏过渡
  3. 机械感:缺少生命力和情感
  4. 认知违和:与用户的运动预期不符

非线性运动的优势:

7.2.2 标准缓动函数

缓动函数将归一化时间t∈[0,1]映射到进度值p∈[0,1]:

Ease-In(缓入)

数学表达: 
- 二次: f(t) = t²
- 三次: f(t) = t³
- 四次: f(t) = t⁴
- 五次: f(t) = t⁵

特征分析:
- 导数: f'(t) = n·t^(n-1) (速度递增)
- 起始速度: f'(0) = 0 (静止开始)
- 结束速度: f'(1) = n (最大速度)

应用场景:
- 物体离开屏幕(加速离开)
- 下落运动(重力加速)
- 消失动画(快速消失)
- 菜单收起(加速收缩)

Ease-Out(缓出)

数学表达:
- 二次: f(t) = 1 - (1-t)²
- 三次: f(t) = 1 - (1-t)³
- 四次: f(t) = 1 - (1-t)⁴
- 五次: f(t) = 1 - (1-t)⁵

特征分析:
- 导数: f'(t) = n(1-t)^(n-1) (速度递减)
- 起始速度: f'(0) = n (最大速度)
- 结束速度: f'(1) = 0 (静止结束)

应用场景:
- 物体进入屏幕(减速进入)
- 停止运动(缓慢停止)
- 出现动画(优雅出现)
- 菜单展开(减速展开)

Ease-In-Out(缓入缓出)

数学表达:
标准形式: f(t) = t < 0.5 ? 2t² : 1 - 2(1-t)²

通用形式(n次方):
f(t) = t < 0.5 
     ? 2^(n-1) · t^n 
     : 1 - 2^(n-1) · (1-t)^n

特征分析:
- 对称性: f(t) + f(1-t) = 1
- 中点速度最大: f'(0.5) = max
- 两端速度为零: f'(0) = f'(1) = 0

应用场景:
- 元素位置转换(平滑过渡)
- 页面切换(自然转场)
- 大多数UI动画(通用选择)
- 焦点转移(流畅切换)

Power缓动族

幂函数族提供不同强度的加速效果:

缓动强度对比:
       t=0.25  t=0.5  t=0.75
Linear:  0.25   0.50   0.75
Quad:    0.06   0.25   0.56  (t²)
Cubic:   0.02   0.13   0.42  (t³)
Quart:   0.004  0.06   0.32  (t⁴)
Quint:   0.001  0.03   0.24  (t⁵)

选择指南:

三角函数缓动

使用正弦和余弦创造平滑曲线:

Sine缓动:
- Ease-In: f(t) = 1 - cos(t × π/2)
- Ease-Out: f(t) = sin(t × π/2)
- Ease-In-Out: f(t) = 0.5 × (1 - cos(t × π))

特点:
- 比Power函数更平滑
- 导数连续,无突变点
- 自然的波动感

指数缓动

创造极端的加速效果:

Exponential缓动:
- Ease-In: f(t) = 2^(10(t-1))
- Ease-Out: f(t) = 1 - 2^(-10t)
- Ease-In-Out: 
  f(t) = t < 0.5 
       ? 2^(10(2t-1))/2
       : 1 - 2^(10(1-t))/2

特点:
- 极端的速度变化
- 适合强调和爆炸效果
- 谨慎使用,容易过度

7.2.3 贝塞尔曲线详解

三次贝塞尔曲线是CSS和大多数动画库使用的标准,提供了极大的灵活性:

数学基础

参数方程:
B(t) = (1-t)³P₀ + 3(1-t)²tP₁ + 3(1-t)t²P₂ + t³P₃

展开形式:
B(t) = P₀(1-3t+3t²-t³) + P₁(3t-6t²+3t³) + P₂(3t²-3t³) + P₃t³

对于动画曲线,固定端点:
P₀ = (0, 0) - 起始点
P₃ = (1, 1) - 结束点
P₁ = (x₁, y₁) - 第一控制点
P₂ = (x₂, y₂) - 第二控制点

几何理解

控制点的作用:
  1 |     P₃(1,1)
    |    ╱│
    |   ╱ │P₂ (拉力点)
    |  ╱  │
    | ╱   │P₁ (推力点)
  0 |╱____│_____
    0     1

P₁控制起始切线方向和强度
P₂控制结束切线方向和强度

De Casteljau算法

贝塞尔曲线的几何构造方法:

t时刻的点通过递归线性插值得到:
Q₀ = (1-t)P₀ + tP₁
Q₁ = (1-t)P₁ + tP₂
Q₂ = (1-t)P₂ + tP₃

R₀ = (1-t)Q₀ + tQ₁
R₁ = (1-t)Q₁ + tQ₂

B(t) = (1-t)R₀ + tR₁

常用贝塞尔曲线库

Material Design:
- Standard: cubic-bezier(0.4, 0.0, 0.2, 1)
- Decelerate: cubic-bezier(0.0, 0.0, 0.2, 1)
- Accelerate: cubic-bezier(0.4, 0.0, 1, 1)
- Sharp: cubic-bezier(0.4, 0.0, 0.6, 1)

iOS Human Interface:
- ease: cubic-bezier(0.25, 0.1, 0.25, 1)
- ease-in: cubic-bezier(0.42, 0, 1, 1)
- ease-out: cubic-bezier(0, 0, 0.58, 1)
- ease-in-out: cubic-bezier(0.42, 0, 0.58, 1)

自定义效果:
- 弹性: cubic-bezier(0.68, -0.55, 0.265, 1.55)
- 回弹: cubic-bezier(0.175, 0.885, 0.32, 1.275)
- 预备: cubic-bezier(0.6, -0.28, 0.735, 0.045)

控制点约束

CSS中的cubic-bezier函数有特定约束:

有效范围:
x₁, x₂ ∈ [0, 1]
y₁, y₂ ∈ (-∞, +∞)

超调效果:
y > 1: 超过目标值
y < 0: 反向运动

贝塞尔曲线调试技巧

  1. 切线法则:P₁控制起始速度,P₂控制结束速度
  2. 对称性:(x₁,y₁)和(1-x₂,1-y₂)产生对称曲线
  3. 线性近似:P₁=(0.33,0.33), P₂=(0.67,0.67)接近线性
  4. 极限情况:P₁=(0,0), P₂=(1,1)完全线性

7.2.4 弹性与阻尼动画

弹性动画模拟弹簧的物理特性,创造自然的振荡效果:

物理模型

弹簧-质量-阻尼系统:

     ╱╲╱╲╱╲ k (弹簧)
    │     │
    │  m  │ (质量)
    │     │
    ├─┴─┴─┤ c (阻尼器)
    
运动方程:
mẍ + cẋ + kx = 0

标准形式:
ẍ + 2ζωₙẋ + ωₙ²x = 0

其中:
ωₙ = √(k/m) - 自然频率
ζ = c/(2√(km)) - 阻尼比

解析解

根据阻尼比ζ的不同,系统有三种行为:

1. 欠阻尼 (ζ < 1) - 振荡衰减:
x(t) = Ae^(-ζωₙt) × cos(ωdt + φ)
ωd = ωₙ√(1-ζ²) - 阻尼频率

2. 临界阻尼 (ζ = 1) - 最快收敛:
x(t) = (A + Bt)e^(-ωₙt)

3. 过阻尼 (ζ > 1) - 缓慢收敛:
x(t) = Ae^(r₁t) + Be^(r₂t)
r₁,₂ = -ωₙ(ζ ± √(ζ²-1))

参数影响

阻尼比ζ的效果:
ζ = 0.1: 多次振荡,缓慢衰减
ζ = 0.3: 中等振荡,适中衰减
ζ = 0.5: 少量振荡,快速衰减
ζ = 0.7: 轻微振荡,很快稳定
ζ = 1.0: 无振荡,最快到达
ζ = 1.5: 无振荡,缓慢接近

自然频率ωₙ的效果:
ωₙ↑: 振荡更快,周期更短
ωₙ↓: 振荡更慢,周期更长

实用参数配置

UI动画常用配置:

轻快弹性:
- stiffness: 300
- damping: 20
- mass: 1
- ζ ≈ 0.36

标准弹性:
- stiffness: 100
- damping: 10
- mass: 1
- ζ ≈ 0.5

重型弹性:
- stiffness: 50
- damping: 15
- mass: 2
- ζ ≈ 0.75

RK4数值积分

对于复杂的弹性系统,使用四阶龙格-库塔法:

状态向量: S = [x, v]
导数函数: f(S, t) = [v, -(2ζωₙv + ωₙ²x)]

RK4步骤:
k₁ = h × f(Sₙ, tₙ)
k₂ = h × f(Sₙ + k₁/2, tₙ + h/2)
k₃ = h × f(Sₙ + k₂/2, tₙ + h/2)
k₄ = h × f(Sₙ + k₃, tₙ + h)

Sₙ₊₁ = Sₙ + (k₁ + 2k₂ + 2k₃ + k₄)/6

弹性缓动的变体

1. 弹性进入 (Elastic In):
f(t) = -2^(10(t-1)) × sin((t-1.1)×2π/period)

2. 弹性退出 (Elastic Out):
f(t) = 2^(-10t) × sin((t-0.1)×2π/period) + 1

3. 弹性进出 (Elastic InOut):
前半段使用Elastic In
后半段使用Elastic Out

4. 回弹 (Back):
f(t) = t² × ((s+1)×t - s)
其中s控制回弹幅度,通常s=1.70158

7.3 音乐理论在动效中的应用

7.3.1 节奏与节拍

动效设计可以借鉴音乐的节奏概念:

基础节拍单位

全音符 = 1000ms
二分音符 = 500ms
四分音符 = 250ms
八分音符 = 125ms
十六分音符 = 62.5ms

节奏模式

规则节奏: ● ● ● ● (等间隔)
切分节奏: ● · ● · (长短交替)
渐进节奏: ● ·· ··· ···· (逐渐加密)

7.3.2 动画编排与和声

多个动画元素的协调类似音乐和声:

同步(Unison) 所有元素同时开始和结束:

元素A: ==========>
元素B: ==========>
元素C: ==========>

级联(Cascade) 元素依次开始,创造流动感:

元素A: ==========>
元素B:   ==========>
元素C:     ==========>

交错(Stagger) 部分重叠的动画序列:

元素A: ==========>
元素B:    ==========>
元素C:       ==========>

7.3.3 动画的音乐性参数

Duration(持续时间)

Delay(延迟) 创造节奏感的关键参数:

延迟公式: delay(n) = n × baseDelay
渐进延迟: delay(n) = baseDelay × easing(n/total)

重复与循环

无限循环: animation-iteration-count: infinite
有限重复: animation-iteration-count: 3
交替方向: animation-direction: alternate

7.4 路径动画与运动轨迹

7.4.1 直线与曲线路径

直线路径最简单但往往不够自然:

直线插值: P(t) = P₀ + t(P₁ - P₀)

曲线路径更接近自然运动:

二次贝塞尔路径:
P(t) = (1-t)²P₀ + 2(1-t)tP₁ + t²P₂

7.4.2 SVG路径动画

SVG提供了强大的路径定义语言:

M = moveto(移动到)
L = lineto(直线到)
C = curveto(三次贝塞尔曲线)
Q = quadratic Bézier curve(二次贝塞尔曲线)
A = elliptical Arc(椭圆弧)
Z = closepath(闭合路径)

路径动画的offset-path属性:

轨迹定义: path('M10 10 C 20 20, 40 20, 50 10')
偏移距离: offset-distance: 0% → 100%
旋转对齐: offset-rotate: auto

7.4.3 物理模拟路径

抛物线运动

水平位置: x(t) = v₀ₓ × t
垂直位置: y(t) = v₀ᵧ × t - ½g × t²

圆周运动

x(t) = r × cos(ωt + φ)
y(t) = r × sin(ωt + φ)
其中: r = 半径, ω = 角速度, φ = 初相位

螺旋运动

x(t) = r(t) × cos(θ(t))
y(t) = r(t) × sin(θ(t))
r(t) = r₀ + vᵣ × t (线性增长)
θ(t) = ω × t

7.5 性能优化策略

7.5.1 GPU加速属性

优先使用GPU加速的属性:

避免触发重排的属性:

7.5.2 合成层优化

创建独立合成层:

will-change: transform;
transform: translateZ(0); /* hack */

合成层的内存成本:

内存 = 宽度 × 高度 × 4字节
例: 1920×1080层 = 8.3MB

7.5.3 动画性能监控

关键性能指标:

性能预算:

主线程时间: < 10ms
合成时间: < 3ms
总帧时间: < 16ms

7.5.4 requestAnimationFrame优化

使用RAF同步浏览器刷新:

帧率计算: 
targetFPS = 60
frameTime = 1000 / targetFPS = 16.67ms

时间戳差值:
deltaTime = currentTime - lastTime
progress = deltaTime / duration

7.6 实践技巧与设计模式

7.6.1 微交互动效模式

按钮状态反馈

默认 → 悬停: scale(1.05), 150ms, ease-out
悬停 → 按下: scale(0.95), 100ms, ease-in
按下 → 释放: scale(1), 200ms, elastic

加载状态指示

脉冲效果: opacity 0.5→1→0.5, 1.5s, ease-in-out, infinite
旋转加载: rotate 0→360deg, 1s, linear, infinite
进度条: scaleX 0→1, duration = f(progress)

通知入场动效

滑入: translateY(-100%)→0, 300ms, ease-out
淡入: opacity 0→1, 200ms, ease-in
弹性: scale(0)→1.1→1, 400ms, cubic-bezier

7.6.2 页面转场策略

共享元素过渡 保持关键元素的视觉连续性:

1. 记录起始位置和大小
2. 计算目标位置和大小
3. 应用transform动画
4. 同步其他元素变化

视差滚动 不同层级的差速运动:

背景层: translateY = scrollY × 0.5
中景层: translateY = scrollY × 0.7
前景层: translateY = scrollY × 1.0

渐进式展现 内容分批次加载和显示:

标题: delay = 0ms
副标题: delay = 50ms
内容: delay = 100ms
图片: delay = 150ms

7.6.3 响应式动效适配

设备性能检测

高性能设备: 完整动效,60fps目标
中等设备: 简化动效,降低复杂度
低端设备: 最小动效,仅保留必要反馈

Reduced Motion适配

媒体查询: @media (prefers-reduced-motion: reduce)
策略:
- 移除装饰性动画
- 缩短动画时长
- 使用淡入淡出替代复杂动效

7.6.4 动效调试技巧

Chrome DevTools

性能标记点

开始标记: performance.mark('animation-start')
结束标记: performance.mark('animation-end')
测量: performance.measure('animation', 'animation-start', 'animation-end')

本章小结

动效设计是将时间维度融入用户界面的艺术与科学。通过本章学习,我们掌握了:

  1. 时间函数的数学基础:从线性到贝塞尔曲线,理解不同缓动函数的特性和应用场景
  2. 音乐理论的设计应用:将节奏、节拍、和声概念转化为动画编排原则
  3. 物理模拟的真实感:通过弹簧-阻尼系统和运动学方程创造自然的动效
  4. 性能优化的技术要点:GPU加速、合成层管理、RAF优化等关键技术
  5. 实践模式与调试方法:微交互、转场策略、响应式适配等实用技巧

关键公式回顾:

记住:优秀的动效设计是隐形的——用户感受到的是流畅自然的体验,而非动画本身。

练习题

基础题

练习7.1:缓动函数理解 给定一个元素需要在500ms内从位置x=0移动到x=200px,分别计算使用linear、ease-in(t²)、ease-out(1-(1-t)²)函数时,在t=250ms时元素的位置。

提示:将时间归一化到[0,1]区间,应用缓动函数,再映射到实际位置。

参考答案 时间归一化:t_norm = 250/500 = 0.5 Linear: - f(0.5) = 0.5 - 位置 = 0 + 0.5 × 200 = 100px Ease-in (t²): - f(0.5) = 0.5² = 0.25 - 位置 = 0 + 0.25 × 200 = 50px Ease-out (1-(1-t)²): - f(0.5) = 1-(1-0.5)² = 1-0.25 = 0.75 - 位置 = 0 + 0.75 × 200 = 150px

练习7.2:动画时序设计 设计一个卡片列表的进入动画,有6张卡片需要依次显示。每张卡片动画时长300ms,如何设置延迟使得:

  1. 总动画时长不超过800ms
  2. 动画有层次感
  3. 保持流畅的视觉节奏

提示:考虑动画重叠和级联效果。

参考答案 方案:使用交错动画(stagger) 每张卡片延迟计算: - 卡片1: delay = 0ms - 卡片2: delay = 100ms - 卡片3: delay = 200ms - 卡片4: delay = 300ms - 卡片5: delay = 400ms - 卡片6: delay = 500ms 总时长 = 最后一张卡片延迟 + 动画时长 = 500 + 300 = 800ms 延迟公式:delay(n) = (n-1) × 100ms 重叠时间:200ms(创造流动感)

练习7.3:性能优化判断 以下CSS属性变化,哪些会触发重排(reflow),哪些只触发重绘(repaint),哪些可以仅在合成层处理?

  1. transform: translateX(100px)
  2. width: 200px → 300px
  3. opacity: 1 → 0.5
  4. background-color: red → blue
  5. left: 0 → 100px
  6. filter: blur(5px)

提示:考虑浏览器渲染管线的不同阶段。

参考答案 1. transform: translateX(100px) - 仅合成层(GPU加速) 2. width: 200px → 300px - 触发重排(影响布局) 3. opacity: 1 → 0.5 - 仅合成层(GPU加速) 4. background-color: red → blue - 触发重绘(不影响布局) 5. left: 0 → 100px - 触发重排(影响布局) 6. filter: blur(5px) - 仅合成层(GPU加速) 优化建议:优先使用transform和opacity实现动画效果。

挑战题

练习7.4:贝塞尔曲线设计 设计一个”弹跳”效果的贝塞尔曲线,要求:

  1. 动画开始缓慢
  2. 中间有超调(overshoot)
  3. 结束时有小幅回弹 请给出cubic-bezier的四个参数值,并解释选择理由。

提示:P1控制起始切线,P2控制结束切线,y值可以超过1。

参考答案 建议参数:cubic-bezier(0.68, -0.55, 0.265, 1.55) 解释: - P1(0.68, -0.55):x=0.68使起始缓慢,y=-0.55创造初始的反向运动 - P2(0.265, 1.55):x=0.265控制结束速度,y=1.55创造超调效果 这个曲线会产生: 1. 开始时略微后退(负值) 2. 快速加速超过目标值(>1) 3. 最后回弹到目标位置 适用场景:弹性菜单、强调性动画、游戏化界面元素。

练习7.5:复合动画编排 设计一个模态框的完整动画序列,包括:

提示:考虑动画的层次关系和用户注意力流向。

参考答案 完整时间轴设计(总时长600ms): 0-200ms: 背景遮罩 - opacity: 0→0.5 - easing: ease-out 100-400ms: 模态框主体 - translateY: 100%→0 - scale: 0.9→1 - easing: cubic-bezier(0.34, 1.56, 0.64, 1) 300-450ms: 标题 - opacity: 0→1 - translateY: 20px→0 - easing: ease-out 350-500ms: 内容 - opacity: 0→1 - translateY: 20px→0 - easing: ease-out 400-550ms: 按钮 - opacity: 0→1 - scale: 0.8→1 - easing: ease-out 设计理由: 1. 背景先出现,建立层级关系 2. 模态框使用弹性曲线,增加活力 3. 内容元素级联出现,引导阅读顺序 4. 重叠时间创造流畅感

练习7.6:物理动画模拟 实现一个”重力球”动画:球从高处落下,碰到地面后反弹,每次反弹高度递减,最终静止。给出:

  1. 位置-时间函数
  2. 速度衰减模型
  3. 反弹次数估算

提示:使用能量守恒和恢复系数。

参考答案 物理模型: 1. 下落阶段(自由落体): - $y(t) = h_0 - \frac{1}{2}gt^2$ - $v(t) = -gt$ 2. 反弹模型: - 恢复系数 e = 0.7(能量损失30%) - 反弹速度:$v_{after} = -e \times v_{before}$ - 反弹高度:$h_n = e^2 \times h_{n-1}$ 3. 完整运动方程: ``` 第n次反弹: 高度: h_n = h_0 × e^(2n) 时间: t_n = 2√(2h_n/g) ``` 4. 反弹次数估算: - 停止条件:h_n < 1px - $n > \frac{\ln(1/h_0)}{2\ln(e)}$ - 若h_0=400px, e=0.7, 约需8-9次反弹 5. 实现考虑: - 使用requestAnimationFrame - 速度阈值检测,避免无限微小反弹 - 添加水平阻尼模拟空气阻力

常见陷阱与错误

1. 过度动画

问题:添加过多装饰性动画,影响可用性 解决:每个动画都应有明确目的,遵循”少即是多”原则

2. 忽视性能影响

问题:在低端设备上动画卡顿 解决:实施性能预算,提供降级方案,使用will-change谨慎

3. 时长设置不当

问题:动画太快用户看不清,太慢显得拖沓 解决:遵循平台规范,A/B测试优化,考虑上下文

4. 缺乏一致性

问题:不同组件使用不同的动画风格 解决:建立动画设计系统,定义标准缓动函数库

5. 忽略可访问性

问题:动画对部分用户造成不适 解决:实现prefers-reduced-motion,提供动画开关

6. 滥用弹性效果

问题:所有动画都加入弹性,显得廉价 解决:弹性效果应用于需要强调和活力的元素

7. 动画阻塞交互

问题:用户必须等待动画完成才能操作 解决:支持动画中断,快速连续操作时跳过动画

8. 忽视动画上下文

问题:相同动画用于不同场景 解决:根据触发源、目标、重要性调整动画参数