如何使用JS和p5.js实现类中创建的图形对象持续移动/振动效果
问题原因及修复方案
1. 页面崩溃原因
draw() 是p5.js内置的帧循环函数,默认每秒执行60次。如果在draw()中重复执行new Face(),会持续创建新的实例且没有销毁逻辑,最终内存溢出导致页面崩溃。
正确的做法是仅在setup()中初始化一次Face实例,后续帧循环中直接复用该实例更新状态、重绘即可。
2. OOP添加移动/振动的最佳实现思路
遵循「状态与渲染分离」的原则设计类即可:
- 构造函数仅负责初始化实例属性:基础坐标、半径、振动幅度、顶点数据等核心状态
- 单独定义
update()方法:负责每一帧更新振动/移动的状态参数 - 单独定义
draw()方法:负责读取当前最新状态,执行绘制逻辑
3. 完整可运行代码
JavaScript代码
// 全局存储face实例,避免重复创建 let face; function setup() { createCanvas(350, 350, WEBGL); // 仅初始化一次实例 face = new Face(100, 20, 0, 0); } function draw() { // 每帧清屏 background('white'); // 更新振动状态 face.update(); // 绘制最新状态的图形 face.draw(); } class Face { constructor(radius, steps, baseX, baseY) { // 存储基础属性 this.radius = radius; this.steps = steps; this.baseX = baseX; this.baseY = baseY; // 振动参数:整体偏移振动、边缘抖动幅度可自行调整 this.vibrationStrength = 3; this.edgeJitterStrength = 2; } // 每帧更新状态 update() { // 整体随机振动偏移,也可以用sin/cos实现规律振动 this.offsetX = random(-this.vibrationStrength, this.vibrationStrength); this.offsetY = random(-this.vibrationStrength, this.vibrationStrength); } // 绘制逻辑 draw() { let xValues = []; let yValues = []; // 计算当前帧的顶点坐标 for (let i = 0; i < this.steps; i++) { // 边缘加随机抖动,不需要可以删除这行的random部分 let rad = this.radius + random(-this.edgeJitterStrength, this.edgeJitterStrength); xValues[i] = this.baseX + this.offsetX + rad * cos(2 * PI * i / this.steps); yValues[i] = this.baseY + this.offsetY + rad * sin(2 * PI * i / this.steps); } beginShape(); strokeWeight(4); for (let i = 0; i < xValues.length; i++) { curveVertex(xValues[i], yValues[i]); } endShape(CLOSE); } }
HTML代码(无需修改)
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.js"></script>
自定义调整说明
- 要修改振动幅度,调整
vibrationStrength的数值即可,数值越大振动越剧烈 - 要修改边缘抖动幅度,调整
edgeJitterStrength的数值即可,设为0就是边缘平滑的圆形 - 要实现规律性的移动而非随机振动,把
update()里的random替换为sin(frameCount * 0.1) * vibrationStrength即可得到正弦规律的往复运动
内容的提问来源于stack exchange,提问作者billyjean
相关产品推荐
相关产品推荐

