← 返回

用交互动画理解折射角 (Snell 定律可视化)

2025-09-17

当一束光从一种介质(折射率 n₁)进入另一种介质(折射率 n₂)时,传播方向会发生改变,这就是折射。其定量关系由经典的 Snell 定律 给出:

n₁ · sin θ₁ = n₂ · sin θ₂

其中:

  • n₁, n₂ 分别是第一、第二介质的折射率
  • θ₁ 是入射角(光线与法线之间的夹角)
  • θ₂ 是折射角(折射光线与法线之间的夹角)

下面这个交互式组件可以帮助你更直观地理解:拖动滑块修改第二介质折射率 n₂,或在上方拖动光线,观察折射角变化及全反射出现的瞬间。

θ1θ1θ2
First Medium
n1 = 1
Second Medium
n2 = 1.50
Normal
0.013
n21.5

交互玩法

  • 拖动下方滑块:连续调整折射率 n₂ (范围 0.01 → 3)
  • 在上方光线区域左右拖动:改变入射角 θ₁
  • 当 n₁ > n₂ 且入射角足够大时,会出现 全反射(看不到折射光,仅看到反射延长线)
  • 点击右下角 Replay 按钮:重新播放预设演示动画

视觉元素说明

元素含义
水平线两种介质分界面
竖虚线法线(Normal)
左上角彩色入射光Incident Ray
下方彩色折射光Refracted Ray(若全反射则消失)
虚线延长入射光/折射光的投影或延长线
弧形与 θ₁ / θ₂ 标注对应的入射/折射角

Snell 定律与临界角

当从高折射率介质进入低折射率介质 (n₁ > n₂) 时,折射角 θ₂ 会比入射角 θ₁ 更大。随着 θ₁ 增大,θ₂ 逐渐逼近 90°。当 θ₂ → 90° 时,对应的入射角称为 临界角 θc

sinθc=n2n1\sin\theta_c = \frac{n_2}{n_1}

若 θ₁ > θc,折射不再发生,光线完全被反射回第一介质——这就是全反射

动画实现要点

本组件基于 motion

  • 使用 useMotionValue 管理 n₂、入射角、路径插值进度等状态
  • 使用 useTransform 将角度/比例映射为 SVG 坐标、文本位置、颜色渐变
  • 基于 AnimationSequence 实现一段自动演示序列
  • 通过手势 (onPan) 将用户拖动位置映射为角度
  • 通过 marker 和自定义 <path> 绘制箭头

核心计算:

function calculateRefractionAngle(n1: number, n2: number, theta1: number) {
  const s = (n1 / n2) * Math.sin(theta1);
  if (s > 1 || s < -1) return null; // 全反射
  return Math.asin(s);
}

可以做的扩展

  • 支持多段介质(例如:空气 → 玻璃 → 水)
  • 展示反射光与菲涅尔系数(反射率/透射率)
  • 增加色散:不同波长(颜色)对应不同折射率
  • 展示波前(用一组平行线代替光线)
  • 添加“临界角”动态提示与公式推导动画
  • 添加播放速度与暂停控制

总结

交互式物理可视化能让抽象公式建立直觉联系。借助 Motion 的声明式动画与 SVG 的矢量表达,我们能快速构建一个既美观又具教育意义的光学演示组件。

如果你对更多物理/数学可视化感兴趣,欢迎继续关注后续内容 👋

行内公式示例:n1sinθ1=n2sinθ2n_1\sin\theta_1 = n_2\sin\theta_2,以及临界角 θc\theta_c 与折射率关系 sinθc=n2n1\sin\theta_c=\dfrac{n_2}{n_1}

块级公式测试:

θ2=arcsin(n1n2sinθ1)\theta_2 = \arcsin\left(\frac{n_1}{n_2}\sin\theta_1\right)