李萨如图形 Lissajous Curve 在前端动态背景中的数学推导与 Canvas 绘制

在音频工程、示波器物理实验以及科技感前端界面的动态背景中,经常能看到一种极其优雅、对称且富有生命律动的交织光线——两条或多条发光的连续曲线在屏幕中央像丝绸般缓缓旋转、翻折、交叠,时而呈现出完美的“8”字形,时而演变为包含多个波峰与环扣的花冠多面体。
这种由两个相互垂直的正交简谐振动在平面上合成所形成的复杂几何轨迹,在物理学与数学中被称为 李萨如图形(Lissajous Curve / 鲍迪奇曲线 Bowditch Curve)。
在生成艺术领域,李萨如曲线是利用极简的三角函数方程生成无尽科技美感背景最经典的利器。本文将带大家深入推导其参数方程,并在 HTML5 Canvas 中手写一个带有微光拖尾的动态李萨如背景引擎。
李萨如图形的参数方程数学推导
设一个质点在二维平面中同时参与两个相互垂直的简谐振动:
- X 轴方向的振动位移由正弦波驱动:振幅为 $A$,角频率为 $a$,初相位为 $\delta$;
- Y 轴方向的振动位移由正弦波驱动:振幅为 $B$,角频率为 $b$,初相位为 $0$。
其在任意时刻 $t$ 的平面参数方程为:
$$\begin{cases} x(t) = A \cdot \sin(a \cdot t + \delta) \ y(t) = B \cdot \sin(b \cdot t) \end{cases}$$
轨迹闭合性与频率比 $\frac{a}{b}$ 的几何规律
- 当频率比 $\frac{a}{b}$ 为有理数(Rational Ratio)时:曲线在经历周期 $T = \frac{2\pi}{\gcd(a, b)}$ 后会形成一条完美闭合的静止或呼吸几何图形;
- 若 $a = 1, b = 1, \delta = 0$:轨迹退化为一条斜率为主对角线的直线($y = \frac{B}{A}x$);
- 若 $a = 1, b = 1, \delta = \frac{\pi}{2}$:轨迹演变为一个标准的正椭圆(或正圆);
- 若 $a = 1, b = 2$:轨迹形成经典的抛物线或“8”字形(双纽线形态);
- 若 $a = 3, b = 4$:轨迹演化为包含 3 个横向环与 4 个纵向环的精致花结网格!
- 当相位差 $\delta(t)$ 随时间极缓慢线性漂移时($\delta(t) = \omega_{\delta} \cdot t$):二维平面上的李萨如曲线会在视觉上产生一种宛如在三维空间中围绕中心轴缓缓旋转的逼真立体透视感!
// lissajous-math.ts
export interface LissajousConfig {
a: number; // X 轴频率
b: number; // Y 轴频率
delta: number; // 初始相位差 (弧度)
amplitudeX: number;// X 轴振幅
amplitudeY: number;// Y 轴振幅
speed: number; // 时间流逝速度
phaseDriftSpeed: number; // 相位漂移速度 (驱动 3D 旋转感)
}
export function evaluateLissajousPoint(
t: number,
config: LissajousConfig,
cx: number,
cy: number
): { x: number; y: number } {
const x = cx + config.amplitudeX * Math.sin(config.a * t + config.delta);
const y = cy + config.amplitudeY * Math.sin(config.b * t);
return { x, y };
}
Canvas 动态发光李萨如背景引擎
利用 Canvas 的半透明背景擦除机制,我们可以为运动的李萨如光线赋予一道极富未来感的霓虹光影拖尾:
// lissajous-canvas-stage.ts
export class LissajousStage {
private canvas: HTMLCanvasElement;
private ctx: CanvasRenderingContext2D;
private config: LissajousConfig;
private samplePoints: number = 360; // 单条完整曲线的采样密度
constructor(canvas: HTMLCanvasElement) {
this.canvas = canvas;
this.ctx = canvas.getContext('2d')!;
this.config = {
a: 3,
b: 4,
delta: 0,
amplitudeX: canvas.width * 0.35,
amplitudeY: canvas.height * 0.35,
speed: 0.002,
phaseDriftSpeed: 0.008,
};
}
public renderLoop = (timestamp: number) => {
const w = this.canvas.width;
const h = this.canvas.height;
const cx = w / 2;
const cy = h / 2;
// 动态调制振幅以自适应窗口
this.config.amplitudeX = w * 0.38;
this.config.amplitudeY = h * 0.38;
// 随时间缓慢漂移相位差,产生三维旋转质感
this.config.delta = timestamp * this.config.phaseDriftSpeed * 0.05;
// 绘制半透明深蓝背景 (保留 0.08 透明度产生梦幻微光拖尾)
this.ctx.fillStyle = 'rgba(9, 13, 22, 0.12)';
this.ctx.fillRect(0, 0, w, h);
// 绘制主发光李萨如曲线
this.ctx.beginPath();
this.ctx.strokeStyle = '#6366f1';
this.ctx.lineWidth = 2.0;
for (let i = 0; i <= this.samplePoints; i++) {
const t = (i / this.samplePoints) * (2 * Math.PI);
const pt = evaluateLissajousPoint(t, this.config, cx, cy);
if (i === 0) {
this.ctx.moveTo(pt.x, pt.y);
} else {
this.ctx.lineTo(pt.x, pt.y);
}
}
this.ctx.stroke();
// 叠加第二条相位反向的浅青色伴随曲线 (增强立体多面感)
this.ctx.beginPath();
this.ctx.strokeStyle = 'rgba(56, 189, 248, 0.6)';
this.ctx.lineWidth = 1.2;
for (let i = 0; i <= this.samplePoints; i++) {
const t = (i / this.samplePoints) * (2 * Math.PI);
const x = cx + this.config.amplitudeX * 0.9 * Math.sin(this.config.a * t - this.config.delta);
const y = cy + this.config.amplitudeY * 0.9 * Math.sin(this.config.b * t);
if (i === 0) this.ctx.moveTo(x, y);
else this.ctx.lineTo(x, y);
}
this.ctx.stroke();
requestAnimationFrame(this.renderLoop);
};
}
总结
李萨如图形是纯粹的简谐振动在平面上交织出的数学诗篇。没有复杂的外部模型加载,仅仅凭借两个正弦函数的频率比与相位漂移,我们就在纯前端 Canvas 画布上,以极轻量的算力开销,渲染出了深邃、沉静且极具科技美学张力的动态数字画卷。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/leopold_man/article/details/165237043




