如何让mxGraph径向树布局的边连接到顶点自定义锚点?
mxRadialTreeLayout 仅负责计算顶点的布局坐标,不会自动匹配你预定义的锚点约束,你之前配置的锚点规则仅对用户交互拖拽连线的场景生效。
你可以在径向树布局执行完成后,手动遍历所有边,根据两个顶点的相对位置匹配最近的锚点,写入边的样式即可实现需求。
修改你的代码中布局执行的部分,在radialLayout.execute(parent)之后、graph.getModel().endUpdate()之前插入以下逻辑:
// 遍历所有边匹配最优锚点 const edges = graph.getModel().getDescendants(parent).filter(cell => cell.isEdge()); const allConstraints = mxShape.prototype.constraints; edges.forEach(edge => { const source = edge.getTerminal(true); const target = edge.getTerminal(false); if (!source || !target) return; const sGeo = source.getGeometry(); const tGeo = target.getGeometry(); // 计算两个顶点的中心点坐标 const sCenter = { x: sGeo.x + sGeo.width / 2, y: sGeo.y + sGeo.height / 2 }; const tCenter = { x: tGeo.x + tGeo.width / 2, y: tGeo.y + tGeo.height / 2 }; // 匹配源顶点最优锚点 const stAngle = Math.atan2(tCenter.y - sCenter.y, tCenter.x - sCenter.x); let minDiff = Infinity, bestSrc = allConstraints[0]; allConstraints.forEach(c => { const aAngle = Math.atan2((c.point.y - 0.5) * sGeo.height, (c.point.x - 0.5) * sGeo.width); const diff = Math.min(Math.abs(stAngle - aAngle), 2 * Math.PI - Math.abs(stAngle - aAngle)); if (diff < minDiff) { minDiff = diff; bestSrc = c; } }); // 匹配目标顶点最优锚点 const tsAngle = Math.atan2(sCenter.y - tCenter.y, sCenter.x - tCenter.x); minDiff = Infinity; let bestTgt = allConstraints[0]; allConstraints.forEach(c => { const aAngle = Math.atan2((c.point.y - 0.5) * tGeo.height, (c.point.x - 0.5) * tGeo.width); const diff = Math.min(Math.abs(tsAngle - aAngle), 2 * Math.PI - Math.abs(tsAngle - aAngle)); if (diff < minDiff) { minDiff = diff; bestTgt = c; } }); // 写入边样式 let style = edge.getStyle() || ''; style += `;${mxConstants.STYLE_SOURCE_CONSTRAINT}=${mxUtils.encodeValue(bestSrc)}`; style += `;${mxConstants.STYLE_TARGET_CONSTRAINT}=${mxUtils.encodeValue(bestTgt)}`; graph.getModel().setStyle(edge, style); });
注意事项
- 每次重新执行径向树布局后,都需要重新运行上述锚点匹配逻辑,保证边的连接点和新的顶点位置匹配。
- 如果你为不同顶点自定义了不同的锚点列表,只需将上述代码中的
mxShape.prototype.constraints替换为对应顶点自身的约束列表即可。
内容的提问来源于stack exchange,提问作者user16635610
相关产品推荐
相关产品推荐

