p5.js for循环实现鼠标碰撞检测时重叠气泡文本标签遮挡问题求解
核心解决思路
- 先解决数组无限增长的问题:
draw()函数是每帧执行60次的,你之前只做了符合条件就往数组里加的逻辑,没有每帧开头清空数组,自然会越存越多。 - 不要边遍历气泡边绘制文本:先把当前帧所有符合悬停条件的气泡收集到统一的数组里,再批量处理文本的位置,避免重叠。
- 文本防重叠的简单实现:收集完所有悬停文本后,统一排列在鼠标侧边,每个文本固定垂直偏移,完全不会碰撞。
修正后的完整代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
let bubbles = { pos: [], diam: [], color: [], id: [], // 给每个气泡加独立的半径动画变量,修复原代码全局共用变量导致的动画异常问题 animR: [] } function setup() { createCanvas(600, 400); for (var i = 0; i < 60; i++) { bubbles.pos.push(createVector(random(0, width), random(0, height))); bubbles.color.push(color(random(0, 255), random(0, 255), random(0, 255), 120)); bubbles.diam.push(random(0, 80)); bubbles.id.push(round(random(0, 1000))); bubbles.animR.push(0); } } function draw() { background(10); // 每帧开头先清空悬停气泡列表,防止无限增长 let hoverBubbles = []; const textSizeVal = 20; textSize(textSizeVal); // 第一遍遍历:绘制气泡,同时收集悬停的气泡 for (var i = 0; i < 60; i++) { // 每个气泡独立做半径动画 bubbles.animR[i] += 0.01; let consR = constrain(bubbles.animR[i], 0, bubbles.diam[i]); stroke(0); fill(bubbles.color[i]); ellipse(bubbles.pos[i].x, bubbles.pos[i].y, consR); let dBubbles = dist(mouseX, mouseY, bubbles.pos[i].x, bubbles.pos[i].y); if (dBubbles < bubbles.diam[i] / 2) { // 把悬停的气泡存入数组 hoverBubbles.push(bubbles.id[i]); } } // 第二部分:批量绘制悬停文本,排列在鼠标右侧,上下错开 fill(255); for (let i = 0; i < hoverBubbles.length; i++) { // 每个文本垂直偏移一个字号的高度,完全不会重叠 text(hoverBubbles[i], mouseX + 10, mouseY + i * textSizeVal); } }
其他可选方案
如果需要文本显示在气泡附近而不是鼠标旁,可以给每个文本计算边界盒(用textWidth()获取文本宽度,字号就是高度),逐个检测和之前已绘制的文本是否碰撞,如果碰撞就向下偏移,直到没有重叠为止,逻辑和上面的固定偏移类似,只是把固定偏移换成动态碰撞检测的偏移量即可。
内容的提问来源于stack exchange,提问作者Free_Parallel
相关产品推荐
相关产品推荐

