三角函数:正弦波与圆周运动
噪声用随机信号驱动无尽的微动;三角函数给出另一类不收敛、永不停止的运动——规则的周期。一个 Math.sin(t) 就是最简单的周期性「时间到值」:输入均匀流逝的时间,输出一条在
之间平滑往返、永远重复的曲线。
1 · 三个旋钮
通式是 ,三个参数各管一件互不重叠的事。
振幅 是纵向缩放,把 拉伸到 ,决定往返幅度而不改变节奏。频率 是横向缩放,每秒完成 个完整周期,周期 ;角频率 是它的弧度表述。相位 是横向平移,决定 时停在周期的哪一点。
2 · 圆周运动就是两路正弦
让角度 随时间匀速增长,点 就沿半径 的圆匀速绕行。盯着整个点看是圆周运动——行星轨道、loading 转圈、时钟指针;只盯一个坐标看,那一维的来回就是纯正弦振荡。
余弦不过是相位超前 的正弦(),所以 、 两路天生差四分之一周期。
3 · 行波是相位交错
给相邻元素一个固定的相位差 ,某一时刻它们就停在周期的不同位置,连起来便是一条沿排列方向行进的波。相位差为 0 时所有元素同相,整排一起上下,看不出波。
相位差与时间延迟可以互换:
度等价于延迟
。这与关键帧编排里给一组元素各加一点 delay 的 stagger 是同一回事,只是改用连续相位表达,运动天然循环、无始无终。
4 · 李萨如曲线
、 不再同步,而是各自以频率 、 振荡、相差 。 是简单整数比时,曲线在有限时间内闭合成稳定花纹;比值越接近无理数,图案越久才重复。
注 · 这个 lab 的曲线用 computed 缓存,只在
、、
变化时重算那 481 个采样点;随时间移动的只有一个小圆点。原先的实现靠一个 lastKey 字符串手动比对参数是否变化——迁到 Vue 后这层缓存由响应式系统免费提供,那段脏检查代码直接删掉了。
const TAU = Math.PI * 2;
// 单位圆: 角度 θ 随时间匀速增长, 点的坐标就是 (cos θ, sin θ)
const theta = TAU * freq * t; // ω = 2π·freq
const x = R * Math.cos(theta); // 水平投影 → 余弦
const y = R * Math.sin(theta); // 垂直投影 → 正弦
// 只取一个分量 → 一维振荡 (脉动 / 上下浮动)
const bob = amplitude * Math.sin(TAU * freq * t + phase);
// 一排元素相位各错开 Δφ → 行波
dots.forEach((el, i) => {
const v = amplitude * Math.sin(TAU * freq * t - i * dPhi);
el.style.transform = `translateY(${v}px)`;
});
// 两轴各跑一个正弦, 频率比 a:b → 李萨如曲线
const px = Math.sin(a * u + delta);
const py = Math.sin(b * u);
至此「不演化到目标」的两类运动都齐了:噪声给出随机而有机的微动,三角函数给出规则而精确的周期。需要演化到固定目标的塑形见缓动,交给物理系统自行收敛的见弹簧。