概述
分層布局弄好之后,每一層的節點上下的相對位置基本確定了,我們最簡單的方式,就是每一層平鋪所有節點,節點寬度固定以及間距固定,每個節點的位置基本就確定了,我們只要基于這些節點進行連線就可以了,
方案思路
直線方式
最簡單的方式就是直線,我們只要確定兩個節點之間的相對具體坐標,然后兩點之間畫一條直線就可以了,效果如下

從上圖可以看出,直線實作起來是比較簡單的,但是節點很少的情況,還是可以勉強可以接受的,如果節點太多,線條復雜,基本沒辦法看了,效果不是很好,
曲線方式
曲線是比較常見的方式,這里可以用3次貝塞爾曲線或者2次貝塞爾曲線,算好相應的控制點即可,但是這些控制點不是很好算,并且通用的一些控制點,在一些復雜情況下,展示的效果也不是很好,這里也沒打算使用這個,
折線方式
就是通過折線,曼哈頓的方式,在空白的地方進行拐點,進行連線,這種方式可以很好利用空間,并且可以規避節點,不會出現 線和節點的相互遮蓋,這里我就采用了這種方式,由于我們的業務場景,節點比較多,并且層級不是很多,這里我投機采用了一種比較簡單的方式來畫這個折線,首先看下效果

在上述情況,我們考慮最簡單的場景,就是最多用4個點來畫這條折線,這種畫法應該是最簡單的,因為圖是從上往下畫的,我們只要考慮 中間節點Y坐標即可,但是要考慮盡可能的不要讓線條重疊, 我們可以把每層節點按照x坐標排序,然后劃線的時候,按照x軸,從左到右的依次劃線,并且保證每條線沒有重疊的部分,
具體實作
節點排序
function divideNodesIntoLayer(nodeList){
// 清空快取的線段結合
nodeLines = {};
var lineNodes = {};
for(var layer = 1; layer <= maxGraphLayer; layer++){
lineNodes[layer] = [];
for(var j = 0; j < nodeList.length; j++){
if(nodeList[j].layer === layer){
lineNodes[layer].push(nodeList[j]);
}
}
lineNodes[layer].sort(function(a, b){
return a.x - b.x;
})
}
return lineNodes;
}
從距離下層節點40px的地方,往上遍歷,每次增加一個步長,判斷是否用重疊,直到找到一個不重疊的Y值為止,
function calcMidY(){
var midY = endY - 40;
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(startX, endX, line.startX, line.endX)) {
flag = true;
}
}
if (flag) break;
}
} else {
nodeLines[layer] = [];
}
if (!flag) break;
midY -= lineDis;
}
if (startX !== endX) {
// 快取已經畫的線段
nodeLines[layer].push({
startX: startX,
startY: midY,
endX: endX,
endY: midY
})
}
}
找到了拐點的Y值,整條折線的坐標都清晰了,根據4個點劃線即可,
總結
以上是一種很簡單的實作方式,遇到復雜場景,還是會有線條的重疊,更準確的做法是要規避所有障礙,尋找路徑,這種復雜的做法,后續會進一步嘗試,
本文由華為云發布,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/454646.html
標籤:其他
