能否基于网格边界实现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
相关产品推荐
相关产品推荐

