You need to enable JavaScript to run this app. 能否基于网格边界实现mouseover事件以显示对应单元格的受力值?
优惠活动
大模型
产品
解决方案
定价
更多

能否基于网格边界实现mouseover事件以显示对应单元格的受力值?

实现方案

该需求完全可行,你已经完成了核心的坐标检测逻辑,只需对事件触发和渲染逻辑做少量调整即可实现。


调整步骤说明

1. 替换触发事件

你当前绑定的是mousedown点击事件,要实现悬停实时响应,直接把事件替换为mousemove即可。

2. 解决Canvas残影问题

Canvas是立即渲染模式,直接在画布上绘制文本不会自动清除上一次的绘制结果,会出现文本重叠的残影。有两种可选解决方案:

  • 每次触发mousemove时先清空画布,重绘基础网格和受力云图,再绘制当前的受力值
  • 额外加一个浮动的HTML div元素专门用来显示数值,不需要修改Canvas内容,只需要动态调整div的位置和文本,性能更好

3. 适配变形单元格的检测逻辑

你当前用的轴对齐包围盒检测,仅适用于未发生剪切/变形的正矩形单元格。如果你的FEA模拟中单元格会变形为任意四边形,需要替换为点在多边形内的检测算法(射线法),用你存储的四个角点坐标做精确判断。

4. 性能优化

如果你的网格单元数量超过1000个,每次mousemove全量遍历会有卡顿,可以增加匹配到单元就跳出遍历的逻辑,或者用空间划分(如四叉树)缩小检测范围。


改进后完整代码示例

// 你原来的网格绘制函数,需要提前封装好,每次重绘调用
function drawGrid() {
  // 这里放你原来绘制网格、受力云图的所有逻辑
}

// 实时检测鼠标位置并绘制受力值
function showForceOnHover(canvas, event){
  let rect = canvas.getBoundingClientRect()
  let x = event.clientX - rect.left
  let y = event.clientY - rect.top
  
  // 先清空画布,重绘基础网格,避免文本残影
  context.clearRect(0, 0, canvas.width, canvas.height)
  drawGrid()
  
  // 遍历检测鼠标在哪个单元内
  let matchedForce = null
  for(let i = 0; i < plateForces.length; i++){
    // 如果是未变形的矩形,用你原来的判断即可
    if( plateForces[i][0] < x && x <= plateForces[i][4] && plateForces[i][1] < y && y <= plateForces[i][5] ) {
      matchedForce = plateForces[i][8].toFixed(1)
      break // 找到第一个匹配的就跳出,减少遍历
    }
    // 如果是变形的任意四边形,替换上面的判断为点在多边形检测,调用下面的pointInPoly函数
    // const cellPoints = [
    //   [plateForces[i][0], plateForces[i][1]],
    //   [plateForces[i][2], plateForces[i][3]],
    //   [plateForces[i][4], plateForces[i][5]],
    //   [plateForces[i][6], plateForces[i][7]]
    // ]
    // if(pointInPoly(x, y, cellPoints)) {
    //   matchedForce = plateForces[i][8].toFixed(1)
    //   break
    // }
  }
  
  // 找到匹配的单元就绘制数值
  if(matchedForce) {
    context.fillStyle = "black";
    context.font = "bold 20px Arial"; // 注意你原来的字体拼写错误,正确为Arial
    context.fillText(matchedForce, x, y);
  }
}

// 可选:点在任意四边形内检测(射线法)
function pointInPoly(px, py, vertices) {
  let inside = false
  for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) {
    const xi = vertices[i][0], yi = vertices[i][1]
    const xj = vertices[j][0], yj = vertices[j][1]
    const intersect = ((yi > py) != (yj > py))
        && (px < (xj - xi) * (py - yi) / (yj - yi) + xi)
    if (intersect) inside = !inside
  }
  return inside
}

// 替换原来的mousedown监听为mousemove
canvas.addEventListener('mousemove', function(e) { showForceOnHover(canvas, e) });

内容的提问来源于stack exchange,提问作者buenosdiaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 18:54:08