如何实现拖拽多边形仅触碰其他多边形顶点时触发颜色变更
嘿,这个问题我熟!之前用包围盒(宽高)判断碰撞确实会出现“提前变色”的问题,毕竟包围盒是把整个图形框起来的,只要靠近就会触发。要实现只有拖拽图形的顶点碰到其他图形的顶点才变色,核心就是做顶点级的碰撞检测,而不是用整个图形的边界。
我给你一步步拆解怎么做:
第一步:写一个顶点碰撞检测的工具函数
因为像素级的精准碰顶点很难(用户拖拽的时候不可能完全对准),所以我们需要设一个“容错阈值”——只要两个顶点的距离小于这个阈值,就判定为碰撞。用距离平方来计算比开根号更快,性能更好:
// 判断两个顶点是否碰撞,threshold是容错范围(单位:像素) function isPointsColliding(pointA, pointB, threshold = 5) { const dx = pointA.x - pointB.x; const dy = pointA.y - pointB.y; // 计算两点距离的平方(避免Math.sqrt,提升性能) const distanceSquared = dx * dx + dy * dy; // 比较距离平方和阈值平方的大小 return distanceSquared <= threshold * threshold; }
你可以根据自己的图形大小调整threshold,比如5-10px都比较合适,用户体验会更好。
第二步:替换原来的碰撞判断逻辑
假设你现在有:
draggingPolygon:当前正在拖拽的多边形对象,它的vertices数组存储了所有顶点的{x, y}坐标polygons:页面上所有多边形的数组,每个多边形有vertices、color(当前颜色)、originalColor(初始颜色,用来重置)
那在拖拽事件的处理函数里,把原来基于宽高的判断换成下面的逻辑:
// 先把所有多边形的颜色重置回原始状态,避免残留之前的碰撞效果 polygons.forEach(poly => { poly.color = poly.originalColor; }); // 遍历拖拽多边形的每一个顶点 draggingPolygon.vertices.forEach(dragVertex => { // 遍历其他所有多边形 polygons.forEach(poly => { if (poly === draggingPolygon) return; // 跳过自己,不用检测和自己的碰撞 // 遍历当前多边形的每一个顶点 poly.vertices.forEach(polyVertex => { // 如果两个顶点碰撞了 if (isPointsColliding(dragVertex, polyVertex)) { // 触发颜色变更:比如把被碰的多边形变红,拖拽的变绿 poly.color = '#ff0000'; draggingPolygon.color = '#00ff00'; // 如果只需要触发一次碰撞效果,可以在这里加break或者标记 } }); }); });
第三步:别忘了初始化原始颜色
在创建多边形的时候,一定要给每个多边形加上originalColor属性,保存它的初始颜色,这样在没有碰撞的时候才能恢复回去:
// 示例:创建多边形时的代码 const newPolygon = { vertices: [{x: 100, y: 100}, {x: 200, y: 100}, {x: 150, y: 180}], color: '#333333', originalColor: '#333333' // 保存初始颜色 }; polygons.push(newPolygon);
这样改完之后,就只有当拖拽多边形的某个顶点,靠近其他多边形的顶点(在你设置的阈值范围内)时,才会触发颜色变更,完美解决之前“提前变色”的问题啦!
内容的提问来源于stack exchange,提问作者Dennis Braun
相关产品推荐
相关产品推荐

