资讯动态

用 p5.js 实现叠加波(Additive Waves):从正弦波类到多波叠加动画

发布时间:2026/10/14 16:55:15 来源:尧图企业网站定制
教程文档示例工程【免费下载链接】website-archiveArchive of the Coding Train website (first version)项目地址https://gitcode.com/gh_mirrors/we/website-archive点击查看免费下载在《Nature of Code》第三章振荡系列的 3.7 节中Coding Train 的 Daniel Shiffman 在前两节3.5 简谐运动、3.6 绘制正弦波的基础上进一步将正弦波封装成包含振幅amplitude、周期period与相位phase的 Wave 类并演示如何把多条波形相加得到复杂而富有生命感的叠加波动画。本文以该节课程为骨架结合仓库中的真实源码wave.js 与 sketch.js逐行讲解 Wave 类的设计动机、叠加原理的数学本质以及完整的可运行实现帮助你掌握用类封装波动、以线性叠加生成复杂波形这一可复用的可视化编程范式。一、课程脉络为什么需要 Wave 类叠加波Additive Waves并非凭空出现它是第三章振荡主题的收尾之一前两节分别解决了两个基础问题3.5 简单谐波运动Simple Harmonic Motion用sin()让圆半径或物体位置随时间往复变化引入振幅与周期的概念见 _learning/nature-of-code/3.5-simple-harmonic-motion.md 及对应示例 main/sketch.js。3.6 绘制正弦波Graphing Sine Wave把正弦函数沿 x 轴绘制成波形曲线并试验改变周期与相位带来的形态变化见 _learning/nature-of-code/3.6-graphing-sine.md 与 graphing-wave/sketch.js。在 3.6 的示例中波形是数据驱动的——用一个角度数组逐点计算 y 值。而到了 3.7作者换了一种思维方式把一条波抽象成一个对象每个对象自带振幅、周期与相位三个属性并提供一个给定 x 计算 y的接口。这样做的直接好处是我们可以轻易地创建多条波、让它们各自独立演化再把它们的输出相加一次性得到叠加后的复杂波形。二、Wave 类源码逐行剖析仓库中的 Wave 类实现非常精炼完整代码位于 learning/nature-of-code/3.7-additive-waves/P5/wave.jsclass Wave { constructor(amp, period, phase) { this.amplitude amp; this.period period; this.phase phase; } evaluate(x) { return sin(this.phase (TWO_PI * x) / this.period) * this.amplitude; } update() { this.phase 0.05; } }这个类只做三件事分别对应三个方法成员类型含义说明amplitude数值振幅决定波峰波谷离中心线的最大距离即纵向强度period数值周期波完成一个完整循环所需的 x 跨度像素值越大波形越疏phase数值相位波的起始角度偏移弧度决定波形在 x 轴上的平移位置evaluate(x)方法求值给定水平坐标 x返回该点的 y 偏移量update()方法演化每帧给相位增加固定增量让波流动起来evaluate()一条正弦波的数学内核evaluate(x)是理解整节课的关键其内部公式为y sin(phase (TWO_PI * x) / period) * amplitude把它拆开看(TWO_PI * x) / period当 x 从 0 走到period时括号内的角度恰好从 0 走到TWO_PI即 2π一个完整弧度循环。也就是说周期越大波在屏幕上被拉伸得越平缓。phase在角度上叠加一个起始偏移。改变相位相当于把整条波形沿 x 方向平移是 3.6 节末尾改变起始角度思想的延续。外层乘以amplitude把sin()输出的 [-1, 1] 范围缩放为 [-amplitude, amplitude]决定波的实际高度。与 3.6 中map(sin(angle), -1, 1, -200, 200)的做法不同这里用乘法缩放而非map()映射——代码更简洁且振幅与周期、相位被清晰地封装为对象属性职责分明。update()相位驱动的流动动画update()每帧执行this.phase 0.05。由于相位进入sin()的角度参数相位的持续增长会让波形在水平方向上匀速平移看起来就像波在流动。固定增量 0.05 弧度/帧意味着每帧移动约 0.05/(2π) 个周期节奏平稳。你可以把 0.05 提为可配置的速度属性如this.phaseSpeed让每条波拥有不同的流速。三、叠加原理为什么把波相加会产生新波形单个正弦波是平滑规律的而叠加多条不同参数的正弦波能得到更丰富、更接近自然现象的波形。仓库主程序 learning/nature-of-code/3.7-additive-waves/P5/sketch.js 正是这一思想的实现let waves []; function setup() { createCanvas(600, 400); for (let i 0; i 5; i) { waves[i] new Wave(random(20, 80), random(100, 600), random(TWO_PI)); } } function draw() { background(0); for (let x 0; x width; x 10) { let y 0; for (let wave of waves) { y wave.evaluate(x); } noStroke(); ellipse(x, y height / 2, 16); } for (let wave of waves) { wave.update(); } }关键设计点 1随机参数生成多样波形setup()中创建 5 条波每个参数都在合理区间内随机取值振幅random(20, 80)像素保证叠加后总振幅不至于轻易超出 400 像素的画布高度5 条波的最大叠加幅度理论上可达 5×80400但相位与周期差异使实际叠加结果通常远小于理论极值。周期random(100, 600)像素覆盖从紧密到舒展的波长范围让叠加结果出现明显的高低错落。相位random(TWO_PI)即 0 到 2π 的均匀随机弧度使各条波起始位置互不相同避免所有波峰对齐产生过度规则的效果。关键设计点 2逐点求和 线性叠加draw()的核心是双重循环外层循环以x 10的步长在画布上采样 60 个水平位置600/10内层循环遍历所有 Wave把wave.evaluate(x)的结果累加到y上最终在(x, y height / 2)处绘制一个 16 像素直径的圆。注意y height / 2因为叠加结果可能是负值加上画布高度的一半作为纵向偏移把波形整体沉到画布中央确保负的 y 值也能显示在屏幕内。从数学上看这就是波的线性叠加superposition复合波形在任意点的位移等于各分量波在该点位移的代数和。这一思想也是傅里叶分析的最朴素形态——用多个正弦分量逼近复杂周期信号。仓库中的 circular-wave-exercise 已经用过r1 r sin(a * 10 phase) * 50这种在半径上叠加一个正弦扰动的技巧而 3.7 把它推广为任意多条波、任意数量的叠加源。关键设计点 3采样步长与视觉密度x 10的步长决定粒子密度步长越小粒子越密、波形越连续步长越大画面越稀疏会出现明显的点状离散感。这是经典的性能与观感权衡——60 个采样点 × 5 条波的逐帧求值开销极低即使步长减半也能流畅运行。四、完整可运行示例仓库在 learning/nature-of-code/3.7-additive-waves/P5/ 目录下提供了完整项目共三个文件。HTML 入口文件内容如下!DOCTYPE html html head script srchttps://cdn.jsdelivr.net/npm/p51.4.1/lib/p5.min.js/script meta charsetutf-8 / /head body script srcwave.js/script script srcsketch.js/script /body /html运行方式非常简单将 index.html、sketch.js、wave.js 三个文件放入同一目录用任意静态文件服务器打开 index.html例如python3 -m http.server后访问本地端口或直接用浏览器打开该 HTML 文件页面会通过 CDN 加载 p5.js 1.4.1然后在 600×400 的黑色画布上渲染由 5 条随机正弦波叠加而成的流动粒子波形。注意示例依赖 CDN 引入 p5.js离线环境下需要先自行下载并本地化p5.min.js的引用。五、动画机制与改进思路相位累加如何产生运动整个动画唯一的状态变化来自update()的相位累加。每条波以固定速度0.05 弧度/帧推进自身相位由于各条波的振幅、周期、相位都不同它们叠加后的复合波形既保持连贯的运动感又不会出现所有波峰同步的单调模式。若把三条以上波的速度设为不同值还能产生类似拍频的周期性聚散效果。值得尝试的改进方向平滑连线当前实现用独立圆点绘制可改用beginShape()/vertex()/endShape()把所有采样点连成一条平滑曲线直观展示叠加后的波形轮廓。逐波配色为每条 Wave 增加颜色属性绘制时按波或按位置着色体现多条波同时存在的结构感课程页中社区贡献的 lines with some nice looking gradient 正是梯度配色思路。交互参数将振幅、周期、相位暴露为滑块如贡献者 Abhay Kashyap 的 ColorFull Sine Wave with some sliders实时调整观察叠加结果如何随单个参数变化。动态数量让波的数量随时间或鼠标位置变化观察叠加分量增多时复合波形逐渐粗糙化的过程。回归物理叠加波的思想在 Coding Challenge #159 简单摆模拟本课视频的关联推荐中也有呼应——摆动本身即可视为正弦振荡的叠加。六、学习路径与仓库导航叠加波是振荡 → 波动 → 复杂现象链条上承上启下的一环。建议按以下顺序在仓库中对照学习简谐运动基础_learning/nature-of-code/3.5-simple-harmonic-motion.md振幅与周期的引入正弦波绘制_learning/nature-of-code/3.6-graphing-sine.md周期、相位的图形化实验含 4 个变体示例三角函数与极坐标_learning/nature-of-code/3.4-polar-coordinates.mdsin/cos 的几何直觉本节核心实现_learning/nature-of-code/3.7-additive-waves.md课程主页含章节时间戳与社区贡献列表源码见 3.7-additive-waves/P5/延伸挑战Coding Challenge #159 简单摆 与 #116 利萨茹曲线可在 CodingChallenges 目录中找到对应源码。整套课程源自 Daniel Shiffman 的《The Nature of Code》教材本仓库是 Coding Train 网站的存档版见 README.md_learning/nature-of-code/目录存放课程文档learning/nature-of-code/目录存放对应可运行源码非常适合按视频→文档→源码的顺序系统学习。赞分享教程文档示例工程【免费下载链接】website-archiveArchive of the Coding Train website (first version)项目地址https://gitcode.com/gh_mirrors/we/website-archive点击查看免费下载相关推荐FastLED 波图案Wave Patterns实战指南基于 sin8 与多波叠加的流水、涟漪与海洋动画FastLED 波图案Wave Patterns实战指南基于 sin8 与多波叠加的流水、涟漪与海洋动画 波浪效果是 LED 动画中最常用、也最能体现数嵌入式物联网硬件开发驱动开发如何用ASP.NET API Versioning优雅管理API演进完整入门教程如何用ASP.NET API Versioning优雅管理API演进完整入门教程 在当今的微服务架构和RESTful API设计中API版本管理是每个.NESymPy 光学波动模块 TWave 详解一维横波的符号建模与叠加干涉SymPy 光学波动模块 TWave 详解一维横波的符号建模与叠加干涉 本篇技术指南以 waves.rst https://link.gitcode.com/科学计算符号运算创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑