动画引擎原理 总览待审核
sin/cos · 单位圆 · 李萨如

三角函数:正弦波与圆周运动

噪声用随机信号驱动无尽的微动;三角函数则给出另一类不收敛、永不停止的运动—— 规则的周期。一个 Math.sin(t) 就是最简单的周期性「时间→值」:输入均匀流逝的时间, 输出一条在 −1 与 1 之间平滑往返、永远重复的曲线。给它配上三个旋钮——振幅(往返多远)、 频率(多快重复一次)、相位(从周期的哪一点起步),几乎所有循环类动画(脉动、漂浮、轨道、 波浪)都能由此拼出。

更关键的是:正弦与圆周运动是同一件事。一个点绕单位圆匀速转动,它的两个坐标恰好是 (cos θ, sin θ);盯着整个点看,是圆周运动(轨道、loading 转圈),只盯一个坐标看, 就是上下振荡。本页四个 demo 都由 requestAnimationFrame 持续推进时间 t, 把 sin / cos 实时算出来驱动元素,右侧画出对应的「值随时间」曲线。

小球的垂直位置 = amplitude · sin(2π · frequency · t + phase),中线为 0

同一信号的滚动曲线(最新值在右端,随时间向左推走)

y period T=1/f s ω=2πf rad/s
三个旋钮各管一件事振幅 A 是纵向缩放:把 [−1, 1] 拉伸到 [−A, A],决定往返幅度, 不改变节奏。频率 f 是横向缩放:每秒完成 f 个完整周期,周期 T = 1/f 秒;角频率 ω = 2πf 是它的弧度表述(每秒转过的弧度)。相位 φ 是横向平移:把整条曲线沿时间轴提前或推后, 决定 t=0 时停在周期的哪一点——这正是后面「行波」让一排元素错开的旋钮。三者合成通式 A·sin(ωt + φ),加上一个垂直偏移就能让振荡围绕任意中心进行。

左:点绕圆匀速转,坐标 = (cos θ, sin θ)。右:它的 sin(橙)与 cos(蓝)随 θ 展开成波

θ rad sin θ cos θ
圆周运动与振荡是同一个 sin/cos 的两种看法。让角度 θ = ωt 随时间匀速增长,点 (R·cos θ, R·sin θ) 就沿半径 R 的圆匀速绕行——这就是行星轨道、loading 转圈、 时钟指针。而把这个点投影到一根轴上(只取它的 x 或只取它的 y),那一维的来回运动就是纯正弦振荡。 所以一旦需要「绕圈」就用 cos / sin 配对,需要「来回」就用其中一个;频率改 ω、半径改 R、起始角改相位。 余弦不过是相位超前 90° 的正弦(cos θ = sin(θ + π/2)),因此 x、y 两路天生差四分之一周期。

一排元素同频同幅,只是相位逐个错开:第 i 个 = A·sin(ωt − i·Δφ)

Δφ °/格 每格延迟 s
行波就是相位 stagger。把相位差 Δφ 调到 0,所有元素同相,整排一起上下,看不出波; 一旦给相邻元素一点固定相位差,某一时刻它们就停在周期的不同位置,连起来便是一条沿排列方向行进的波。 相位差 Δφ(度)等价于一个时间延迟 Δφ/360 · T——这与关键帧编排里 给一组元素各加一点 delay 的 stagger 是同一回事,只不过这里用连续相位表达,运动天然循环、无始无终。 波浪式 loading 点、音频频谱条的起伏、随光标流动的网格背景,底层都是这条相位错开的正弦。

两轴各跑一个正弦、频率比 a:b、相差 δ:x=sin(a·u+δ),y=sin(b·u)

频率比 δ °
李萨如曲线:两个正弦各管一根轴。x、y 不再同步,而是各自以频率 a、b 振荡,相差 δ。 当 a:b 是简单整数比时,曲线在有限时间内闭合成稳定花纹(1:1 是椭圆 / 圆 / 直线,取决于 δ; 2:3、3:4 是更复杂的网结);比值越接近无理数,图案越久才重复。这说明高维运动可以拆成几条独立的 一维正弦——把同一套「时间→值」分别接到 x 与 y(乃至缩放、旋转),用频率与相位差调出千变万化的轨迹。
核心 — 同一组 sin/cos,接到不同维度就是不同动画

  

至此「不演化到目标」的两类运动都齐了:噪声给出随机而有机的微动, 三角函数给出规则而精确的周期。需要演化到固定目标的塑形见缓动, 交给物理系统自行收敛的见弹簧