求助:基于指定坐标实现P5.js雨滴波纹屏保的问题
P5.js雨滴波纹屏保实现方案
核心问题分析
- 原始代码直接遍历所有坐标绘制圆圈,且所有圆圈共享同一个尺寸变量,无法控制逐个生成的节奏,导致一次性出现所有波纹。
- 颜色切换逻辑错误:循环设置
fill最终只会应用最后一个颜色,且没有给每个圆圈分配独立的颜色状态,无法实现单个波纹的颜色切换。
修复后的完整代码
// 存储所有波纹的独立状态,每个波纹是一个对象 let ripples = []; // 合并预设坐标为对象数组,更易维护 const locations = [ {x: 50, y: 50}, {x: 50, y: 350}, {x: 100, y: 300}, {x: 150, y: 250}, {x: 100, y: 100}, {x: 150, y: 150}, {x: 200, y: 200}, {x: 250, y: 250}, {x: 300, y: 300}, {x: 350, y: 50}, {x: 300, y: 100}, {x: 250, y: 150}, {x: 350, y: 350}, {x: 50, y: 200}, {x: 100, y: 200}, {x: 300, y: 200}, {x: 350, y: 200}, {x: 200, y: 50}, {x: 200, y: 100}, {x: 200, y: 300}, {x: 200, y: 350} ]; // 预设颜色数组 const colorShift = [color("#00C2BF"), color("#33FFFC"), color("#33A2FF"), color("#3380FF")]; // 控制波纹生成的时间间隔(单位:帧) let spawnInterval = 30; let frameTracker = 0; function setup() { createCanvas(400, 400); background("#004CC2"); noStroke(); // 可根据需求恢复stroke("white")和strokeWeight(1) } function draw() { // 半透明背景实现波纹轨迹淡出效果 background("#004CC2", 10); // 按间隔随机生成新波纹 frameTracker++; if (frameTracker >= spawnInterval) { spawnRandomRipple(); frameTracker = 0; // 随机调整间隔,让生成节奏更自然 spawnInterval = random(20, 60); } // 反向遍历更新波纹,避免删除元素导致的遍历异常 for (let i = ripples.length - 1; i >= 0; i--) { const ripple = ripples[i]; // 扩张波纹尺寸 ripple.size += 1; // 更新颜色索引,实现平滑颜色切换 ripple.colorIndex = (ripple.colorIndex + 0.02) % colorShift.length; // 绘制波纹,取整确保颜色数组索引有效 fill(colorShift[floor(ripple.colorIndex)]); circle(ripple.x, ripple.y, ripple.size); // 当波纹触及画布边缘时移除该波纹 const edgeDistance = min(ripple.x, width - ripple.x, ripple.y, height - ripple.y); if (ripple.size / 2 >= edgeDistance) { ripples.splice(i, 1); } } } // 从预设坐标中随机选取位置生成新波纹 function spawnRandomRipple() { const randomLoc = random(locations); ripples.push({ x: randomLoc.x, y: randomLoc.y, size: 0, // 从0开始扩张 colorIndex: random(0, colorShift.length) // 随机初始颜色 }); }
关键修改说明
1. 独立状态管理解决批量生成问题
- 用
ripples数组存储每个波纹的独立状态(坐标、尺寸、颜色索引),替代原来共享的全局变量,确保每个波纹的生命周期独立可控。 - 通过
spawnRandomRipple函数从预设坐标数组中随机选点,结合帧计数器控制生成间隔,实现波纹逐个随机出现的效果。
2. 单个波纹独立颜色切换
- 给每个波纹分配
colorIndex属性,在绘制循环中逐步递增并对颜色数组长度取模,让每个波纹独立切换颜色。 - 用
floor(ripple.colorIndex)确保从颜色数组中获取有效整数索引,避免颜色异常。
3. 生命周期优化
- 当波纹半径触及画布边缘时,从数组中移除该波纹,避免无效绘制占用性能。
- 使用半透明背景(
background("#004CC2", 10))实现波纹淡出的轨迹效果,比直接重置背景更贴近真实水波视觉。
4. 代码可读性优化
- 将原始的
locationsX和locationsY合并为对象数组,避免坐标对应错误,更易维护。 - 用
const声明常量,提升代码稳定性。
内容的提问来源于stack exchange,提问作者Aidan A.
相关产品推荐
相关产品推荐

