概述
上个版本简略的连线在一些简单场景,尤其层级比拟多,连线跨层级比拟多的状况下,会呈现线条会穿过矩形的状况,这一讲就是在这个根底上,去优化这个连线。
场景剖析
在上面几种状况下,简略版本的画法曾经没法办躲避阻碍节点了。
这种状况,因为简略版本,咱们只在整条门路上增加了2个拐点,这种画法,当呈现上述情况,线条就会被B挡住,理论的需要,咱们要躲避这种节点,绕开。
应该是上面这种状况:
再简单一点的场景如下
这时候有2个节点挡住了。咱们要做的就是依照图示,绕开节点。
思路剖析
察看剖析,咱们要想绕开,一些阻碍节点,咱们先要晓得哪些节点会挡住,才能够绕开。有两个曾经明确数据是,每一层的节点的坐标咱们是晓得,终点p1, 起点是p6。 咱们能够模仿这个过程:
- 如果p1 所在直线没有被最近的下一层挡住,也就是图中D,E,F节点挡住的话,那就阐明,终点能够先画到p2
- 画到p2 之后,持续判断第三层节点,因为B节点会挡住从p2 往下画的竖线,所以绕开B节点,因为P6起点再p2 左侧,所以,在B的左侧找一个空白的中央,即p3
- 当初画到p3了,这时候终点编程p3了, 问题转换成画p1的场景了
- 始终循环,直到到起点这一层,把这个门路上的所有的折点记录下来,就是咱们的门路
具体实现
function drawLine(startX, startY, endX, endY, color, sourceNodeName, targetNodeName, endLayer, startLayer, lineNodes) { var points = []; // 保留门路上的折点 var sx = startX; var ex = endX; for (var layer = startLayer + 1; layer < endLayer; layer++) { // 判断以后这一层有没有节点挡住 var coverRectIndex = -1; for(var i = 0; i < lineNodes[layer].length; i++){ if(lineNodes[layer][i].x < sx && (sx - lineNodes[layer][i].x) < config.rect.width){ coverRectIndex = i; break; } } if(coverRectIndex === -1){ // 如果没有挡住,查看下一层 continue; }else{ // 如果有挡住,则须要依据终点和指标节点绝对地位,决定往左边绕还是后边绕 var midY = lineNodes[layer][coverRectIndex].y - 40; // 计算是右边的空隙还是左边的空隙 var midX = lineNodes[layer][coverRectIndex].x; midX += sx > ex? -(config.rect.space / 2 + config.rect.width) : (config.rect.space / 2 + config.rect.width); while (true) { var flag = false; if (nodeLines[layer]) { for (var i = 0; i < nodeLines[layer].length; i++) { var line = nodeLines[layer][i]; if (line.startY === midY) { if (checkCross(sx, midX, line.startX, line.endX)) { flag = true; } } if (flag) break; } } else { nodeLines[layer] = []; } if (!flag) break; midY -= lineDis; } if (sx !== midX) { nodeLines[layer].push({ startX: sx, startY: midY, endX: midX, endY: midY }) } // 存储门路上点 points.push({ x: sx, y: midY }); points.push({ x: midX, y: midY }); sx = midX; } } // 独自解决最初一层的场景 var midY = lineNodes[endLayer][0].y - 40; while (true) { var flag = false; if (nodeLines[endLayer]) { for (var i = 0; i < nodeLines[endLayer].length; i++) { var line = nodeLines[endLayer][i]; if (line.startY === midY) { if (checkCross(sx, ex, line.startX, line.endX)) { flag = true; } } if (flag) break; } } else { nodeLines[endLayer] = []; } if (!flag) break; midY -= lineDis; } if (sx !== ex) { nodeLines[layer].push({ startX: sx, startY: midY, endX: ex, endY: midY }) } points.push({ x: sx, y: midY }); points.push({ x: ex, y: midY }); return points;}
总结
这里是在原来的根底上进行优化的,实现了躲避阻碍节点的性能。一开始,我想到是 A*算法去搜寻,然而像素点太多,算法复杂度Hold不住,前面卡在缩点的环节上,通过共事的指导,才实现了以后的这种优化,还是要多学习,多总结!
本文由华为云公布