You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 03:36:03