拓撲結(jié)構(gòu)在計算機網(wǎng)絡(luò)設(shè)計和通信領(lǐng)域中非常重要,因為它描述了網(wǎng)絡(luò)中的設(shè)備(即“點”)如何相互連接(即通過“線”)。這種結(jié)構(gòu)不僅涉及物理布局,即物理拓撲,還可以涉及邏輯或虛擬的連接方式,即邏輯拓撲。
	

圖撲軟件自研 HT for Web 產(chǎn)品曾參與搭建了眾多拓撲可視化解決方案。如機房通信拓撲可視化,實現(xiàn)通過圖形圖像直觀展示機房內(nèi)部網(wǎng)絡(luò)設(shè)備、服務器、存儲設(shè)備以及之間連接關(guān)系的技術(shù)。幫助 IT 管理員和網(wǎng)絡(luò)工程師更加直觀地理解機房的網(wǎng)絡(luò)結(jié)構(gòu),便于故障排查、網(wǎng)絡(luò)優(yōu)化和規(guī)劃擴展。
在 HT 中,ht.Node 可充當拓撲圖中的“點”角色,ht.Node 上可顯示圖片圖標,這使得創(chuàng)建拓撲圖時能夠直觀地表示每一個“點”的特征。至于拓撲圖中的“線”,即用于體現(xiàn)兩個節(jié)點之間關(guān)系的元素,可由 ht.Edge 類型承擔這一任務。ht.Edge用于連接起始和目標兩個節(jié)點,兩個節(jié)點間可以有多條ht.Edge存在,也允許起始和目標為同一節(jié)點。
在搭建 HT 拓撲圖前,我們需要先創(chuàng)建一個 HT 的 2D 視圖:
const dm = new ht.DataModel(); // 創(chuàng)建一個數(shù)據(jù)模型 const g2d = new ht.graph.GraphView(dm); // 創(chuàng)建一個 2D 視圖 g2d.addToDOM(); // 將 2D 視圖添加到 body 中 dm.setBackground('rgb(240,237,237)'); // 設(shè)置背景
2D 視圖還可按照需求開啟樹層次渲染:
dm.setHierarchicalRendering(true);
2D 視圖創(chuàng)建完成之后就可以創(chuàng)建“點”和“線”了:
const node1 = createNode('symbols/電信/icon_交換機.json', { x: 0, y: 0 }, "交換機");
const node2 = createNode('symbols/電信/icon_路由.json', { x: 300, y: 0 }, "路由");
createEdge(node1, node2);
function createNode(icon, position, name) {
     const node = new ht.Node(); // 創(chuàng)建一個 ht.Node 節(jié)點
     node.s({
         'label': name,
         'label.color': "#fff"
     });
     node.setImage(icon);
     node.p(position);
     node.setSize({ width: 100, height: 100 });
     dm.add(node); // 將節(jié)點加到數(shù)據(jù)模型中
     return node;
}
function createEdge(source, target, color, reverse) {
     const edge = new ht.Edge(source, target); // 創(chuàng)建一個 ht.Edge
     dm.add(edge); // 將連線節(jié)點加到數(shù)據(jù)模型中
     return edge;
}
運行代碼后的效果:
	
復雜連線
以上展示了一個簡潔的示例,直觀地展現(xiàn)了如何在圖撲自研 HT for Web 中創(chuàng)建節(jié)點并將它們通過連線相連。實際應用中的情形往往更為復雜,需要根據(jù)實際數(shù)據(jù)構(gòu)建拓撲結(jié)構(gòu)。在這個過程中,核心步驟依舊是首先創(chuàng)建 ht.Node 實例以表示各個節(jié)點,再利用 ht.Edge 實例來實現(xiàn)節(jié)點之間的連接。接下來,讓我們通過復雜一些的示例來演示。
創(chuàng)建節(jié)點
為了批量創(chuàng)建節(jié)點并方便管理節(jié)點數(shù)據(jù),示例中定義了結(jié)構(gòu)化的數(shù)據(jù)格式,并將數(shù)據(jù)存儲在一個 JSON 文件中,再通過 ht.Default.xhrLoad() 去獲取到 JSON 文件中的數(shù)據(jù)。獲取到數(shù)據(jù)后就可批量創(chuàng)建節(jié)點。
在實際的運用場景中,也可以通過任何 web 端通訊方式 HTTP/AJAX、WebSocket 去獲取數(shù)據(jù)。
equipment.json 文件中定義的數(shù)據(jù)格式:
[
    {
        "name": "核心交換機1", // 設(shè)備名稱
        "code": "EQ_ASBB1425", // 設(shè)備編碼(唯一標識)
        "icon": "symbols/user/900-word/電信拓撲圖標/icon_核心交換機.json", // 設(shè)備 icon
// 設(shè)備在圖紙中的位置
"size": 60, // 節(jié)點大小
        "position": {
            "x": 0,
            "y": 100
        }
    },
    {
        "name": "核心交換機2",
        "code": "EQ_ASBB1478",
        "icon": "symbols/user/900-word/電信拓撲圖標/icon_核心交換機.json",
        "position": {
            "x": 200,
            "y": 0
        }
    },
    {
        "name": "服務器1",
        "code": "EQ_BCGJ2121",
        "icon": "symbols/user/900-word/電信拓撲圖標/空白服務器.json",
        "position": {
            "x": 200,
            "y": 250
        }
    },
   ...
]
獲取到數(shù)據(jù)并批量創(chuàng)建節(jié)點:
ht.Default.xhrLoad('./equipment.json', function (json) {
       const data = ht.Default.parse(json);
       data.forEach((item) => {
             createNode(item);
        })
})
function createNode(data) {
        const node = new ht.Node();
        node.setTag(data.code); // 設(shè)置節(jié)點唯一標識
        node.setImage(data.icon);
        node.p(data.position);
        node.s('2d.movable', false); // 禁止移動
        node.setSize({ width: data.size || 150, height: data.size || 150 });
        dm.add(node);
         return node;
}
	
創(chuàng)建連線
與節(jié)點數(shù)據(jù)相同,示例中定義了連線對應格式,并且也是存儲在一個 JSON 文件中,再通過 ht.Default.xhrLoad() 獲取數(shù)據(jù)。JSON 文件中定義了連線中最重要的幾個因素:起始節(jié)點、目標節(jié)點、連線顏色。
[
    {
        "source": "EQ_ASBB1425", // 起始節(jié)點的唯一標識
        "target": "EQ_BCGJ2121", // 結(jié)束節(jié)點的唯一標識
        "color": "rgb(0,199,7)" // 連線顏色
    },
    {
        "source": "EQ_ASBB1425",
        "target": "EQ_BCGJ2131",
        "color": "rgb(0,199,7)"
},
...
]
獲取數(shù)據(jù)并且批量創(chuàng)建連線,這一步需要在創(chuàng)建節(jié)點之后執(zhí)行:
ht.Default.xhrLoad('./connectData.json', function (json) {
      const connectData = ht.Default.parse(json);
      connectData.forEach((item) => {
            createEdge(item);
      })
})
function createEdge(data) {
    const source = dm.getDataByTag(data.source);
    const target = dm.getDataByTag(data.target);
    const edge = new ht.Edge(source, target);
    edge.s({
        "edge.color": data.color || "rgb(0,199,7)",
        "edge.width": 4,
        "shadow2.offset.x": -4,
        "shadow2.offset.y": 7,
        "shadow2": true,
        "shadow2.color": "rgba(0,0,0,0.18)",
})
dm.add(edge);
    dm.moveToTop(edge); // 將節(jié)點移動至頂部
    return edge;
}
	
到這里,基本上整個拓撲的效果都已經(jīng)展示出來了,但是可能還存在一些問題。如終端路由之間的連線被服務器擋住了,可能會被認為是路由 1—服務器 1—服務器 2—路由 2 這樣的連接。
	
這種情況下,就可以采用其他的連線方式。ht.Edge 提供了多種的連線方式,可以通過 edge.s(‘edge.type’, 連接方式) 進行設(shè)置。下面展示幾種不同的連接方式:
1.彎曲:edge.s(‘edge.type’, ‘flex2’)
	
2.正交:edge.s(‘edge.type’, ‘ortho2’)
	
3.先水平后垂直:edge.s(‘edge.type’, ‘h.v2’)
	
4.先水平后垂直:edge.s(‘edge.type’, ‘v.h2’)
	
......
ht.Edge 還有很多種的連線方式,這里就先介紹以上幾種方式。
在這個示例內(nèi),兩個路由之間的連線需要跨域多個其他的連線,為了使得連線更加美觀易懂,于是我就這條連線采用了 points 的連線方式,這種方式有極高的靈活性,可在連線路徑上自由地添加控制點,從而實現(xiàn)非常多樣化的效果。
points 類型的連線,有兩個非常重要的屬性:
edge.points:控制點信息;
edge.segments:用來標識在繪制時如何使用 points 數(shù)組中的頂點信息。
將示例中這條連線的連線類型改為 points,并設(shè)置上相應的屬性:
edge.s({
    'edge.type': 'points',
    'edge.center': true,
    'edge.points': [
        { "x": 680, "y": 105 },
        { "x": 490, "y": 200 },
        { "x": 470, "y": 200 },
        { "x": 410, "y": 230 },
        { "x": 400, "y": 250 },
        { "x": 360, "y": 270 },
        { "x": 340, "y": 270 },
        { "x": 260, "y": 310 },
        { "x": 250, "y": 330 },
        { "x": 80, "y": 415 }
    ],
    'edge.segments': [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
});
使用以上 points 連線類型實現(xiàn)的效果:
	
增加背景和裝飾
可創(chuàng)建一些 ht.Shape 節(jié)點作為背景裝飾,突出顯示特定的設(shè)備區(qū)域。
createShape([
    { x: -100, y: 130 },
    { x: 230, y: -50 },
    { x: 340, y: 15 },
    { x: 10, y: 195 },
    { x: -100, y: 130 }
], [1, 2, 2, 2, 5])
createShape([
    { x: -155, y: 354 },
    { x: 575, y: -30 },
    { x: 805, y: 110 },
    { x: 60, y: 510 },
    { x: -155, y: 355 },
], [1, 2, 2, 2, 5]);
createShape([
    { x: 300, y: 470 },
    { x: 660, y: 275 },
    { x: 805, y: 350 },
    { x: 435, y: 550 },
    { x: 300, y: 470 },
], [1, 2, 2, 2, 5])
function createShape(points, segments) {
    const shape = new ht.Shape();
    shape.setPoints(points);
    shape.setSegments(segments);
    shape.s({
        'shape.background': "#fff",
        "shape.border.color": "rgba(13,46,79,0.67)",
        "shape.border.width": 0.5,
    })
    dm.add(shape);
    dm.moveToTop(shape);
    return shape;
}
添加背景后的效果如下:
	
增加一些裝飾的節(jié)點,這些節(jié)點本質(zhì)上也都是 ht.Node,只是顯示了不同的圖標/圖片,效果如下:
	
添加箭頭
在復雜的網(wǎng)絡(luò)拓撲中,連線上常常需要表示數(shù)據(jù)流動方向。在使用圖撲 HT 繪制連線時,ht.Edge 提供了 icons 屬性,通過 icons 屬性,可在 ht.Edge 上定義一系列圖標并設(shè)置它們在連線上的位置。
在設(shè)置 icons 屬性前,需要先注冊好圖標:
ht.Default.setImage('toArrow', {
    width: 40,
    height: 20,
    comps: [
        {
            type: 'shape',
points: [5, 2, 10, 10, 5, 18, 20, 10],
            closePath: true,
            background: 'rgb(0,199,7)',
            borderWidth: 1,
            borderColor: 'rgb(0,199,7)',
            gradient: 'spread.vertical'
        }
    ]
});
ht.Default.setImage('fromArrow', {
    width: 12,
    height: 12,
    comps: [
        {
            type: 'circle',
            rect: [1, 1, 10, 10],
            background: 'rgb(0,199,7)'
        }
    ]
});
在 ht.Edge 上設(shè)置 icons:
edge.addStyleIcon("fromArrow", {
     position: 15, // 圖標位置
     keepOrien: true, // 圖標是否默認自動調(diào)整方向以保持最好的閱讀效果
     names: ['fromArrow']
});
edge.addStyleIcon("toArrow", {
     position: 19,
     keepOrien: true,
     names: ['toArrow']
});
設(shè)置 icons 之后的效果:
	
流動動畫
在圖撲自研產(chǎn)品 HT for Web 中,使用 ht-flow.js 插件,能夠為 ht.Edge 連線添加流動動畫效果。這種效果可用于表示數(shù)據(jù)傳輸、能源流動或任何類型的動態(tài)連接。使用 ht-flow.js 插件實現(xiàn)的流動效果配置起來也十分簡單,正確引入 ht-flow.js 插件后,使用 g2d.enableFlow(60); 開啟流動,再在 ht.Edge 上設(shè)置相應的流動屬性即可。
ht.Edge 配置流動效果的一些屬性說明:
flow:布爾值,設(shè)置為 true 以啟用流動效果。
flow.count:控制流動組的個數(shù),默認為 1。
flow.step:控制流動的步進,默認為 3。
flow.element.count: 每個流動組中的元素的個數(shù),默認為 10。
flow.element.space: 流動組中元素的間隔,默認為 3.5。
flow.element.image: 字符串類型,指定流動組中元素的圖片,圖片需要提前通過 ht.Default.setImage 注冊。目前支持設(shè)置。
flow.element.background: 流動組中元素的背景顏色,默認為 rgba(255, 255, 114, 0.4)。
flow.element.shadow.begincolor: 字符串類型,表示流動組中的元素的漸變陰影的中心顏色,默認為 rgba(255, 255, 0, 0.3)。
flow.element.shadow.endcolor: 字符串類型,表示流動組中的元素的漸變陰影的邊緣顏色,默認為 rgba(255, 255, 0, 0)。
flow.element.shadow.visible:流動陰影是否可見。
flow.begin.percent:開始的位置,值為 0 - 1,默認是 0。
flow.element.autorotate:是否自動朝向,根據(jù)連線的角度自動朝向。
在示例的 ht.Edge 上設(shè)置流動屬性:
edge.s({
        "flow": true,
        "flow.element.background": "rgba(240, 225, 19, 0.5)",
        "flow.element.shadow.begincolor": "rgba(240, 225, 19, 0.5)",
        "flow.element.shadow.endcolor": "rgba(240, 225, 19, 0)",
        "flow.element.count": 1
 });
設(shè)置完成后的效果:
	
在更為復雜的場景中,僅僅依賴簡單的樣式配置難以滿足設(shè)計需求,為此 ht-flow.js 提供了 flow.element.image 屬性,該屬性支持將流動的元素設(shè)置為圖片或圖標,還支持設(shè)置為多個圖片/圖標流動的效果。
在流動上設(shè)置圖標,需要先注冊圖標:
ht.Default.setImage('dataIcon1', {
    "width": 50,
    "height": 50,
    "comps": [
        {
            "type": "shape",
            "background": "rgb(125,195,125)",
            "borderColor": "#979797",
            "points": [
                2.94441,
                16.1039,
                26.41008,
                16.1039,
                26.41008,
                4.28571,
                47.05559,
                25.58442,
                27.23783,
                45.71429,
                27.23783,
                33.84863,
                2.94441,
                33.84863,
                2.94441,
                16.1039
            ]
        }
    ]
})
ht.Default.setImage('dataIcon2', {
    "width": 50,
    "height": 50,
    "comps": [
        {
            "type": "shape",
            "background": "#32D3EB",
            "borderColor": "#979797",
            "points": [
                2.94441,
                16.1039,
                26.41008,
                16.1039,
                26.41008,
                4.28571,
                47.05559,
                25.58442,
                27.23783,
                45.71429,
                27.23783,
                33.84863,
                2.94441,
                33.84863,
                2.94441,
                16.1039
            ]
        }
    ]
});
在 ht.Edge 上設(shè)置屬性:
edge.s({
    "flow": true,
    "flow.element.count": 2,
    "flow.element.image": ["dataIcon1", "dataIcon2"],
    "flow.element.max": 20,
    "flow.element.min": 20,
    "flow.element.shadow.visible": false,
    "flow.element.space": 50,
    "flow.element.autorotate": true
});
設(shè)置完成后的效果:
設(shè)置完成后的效果:
	
拓撲可視化優(yōu)點
直觀性:將抽象的關(guān)系和數(shù)據(jù)通過圖形呈現(xiàn),使得人們可以直觀地理解和分析系統(tǒng)或網(wǎng)絡(luò)的結(jié)構(gòu)。
互動性:現(xiàn)代拓撲可視化工具通常支持用戶與圖形的交互操作,如縮放、拖拽節(jié)點、探索節(jié)點之間的路徑等,進一步提升了分析的深度和廣度。
動態(tài)性:能夠?qū)崟r反映系統(tǒng)或網(wǎng)絡(luò)的變化,及時展現(xiàn)新增元素和調(diào)整后的結(jié)構(gòu)關(guān)系,對于監(jiān)控和管理系統(tǒng)狀態(tài)尤為重要。
靈活性:用戶可以根據(jù)需要選擇不同的布局算法,調(diào)整圖形的展示方式,更好地適應不同的分析場景。
	
	審核編輯 黃宇
- 
                                計算機
                                +關(guān)注
關(guān)注
19文章
7741瀏覽量
92511 - 
                                拓撲結(jié)構(gòu)
                                +關(guān)注
關(guān)注
6文章
332瀏覽量
40704 - 
                                機房
                                +關(guān)注
關(guān)注
0文章
505瀏覽量
17920 
發(fā)布評論請先 登錄
圖撲 HT 驅(qū)動智慧社區(qū)數(shù)字化轉(zhuǎn)型:多維可視化與系統(tǒng)集成實踐
    
圖撲 HT 數(shù)字孿生在智慧加油站中的技術(shù)實現(xiàn)與應用解析
    
圖撲 HT 自研技術(shù)架構(gòu)下 AR 應用開發(fā)與行業(yè)解決方案實現(xiàn)
    
圖撲邀您相聚 2025 國家工業(yè)軟件大會
    
圖撲 HT 技術(shù)賦能智慧畜牧三維可視化:架構(gòu)設(shè)計與實踐應用
    
HT 流暢過渡動畫 × 場景切換實現(xiàn)方案
    
圖撲HT數(shù)字孿生智慧選煤廠的實踐應用
    
基于 HT 引擎鋁型材擠壓車間數(shù)字孿生技術(shù)實現(xiàn)
    
HT 可視化在工業(yè)產(chǎn)線看板智能化應用中的技術(shù)實現(xiàn)
    
再次順利認證 CMMI5!圖撲實力獲國際最高級別認可
    
基于 HT for Web 的輕量化 3D 數(shù)字孿生數(shù)據(jù)中心解決方案
    
基于圖撲 HT 實現(xiàn)的智慧展館數(shù)字孿生應用
    
圖撲數(shù)字孿生:解鎖壓縮空氣儲能管控新高度
    
圖撲 HT 總線式拓撲圖的可視化實現(xiàn)
    
          
        
        
基于圖撲 HT for Web 實現(xiàn)拓撲關(guān)系圖
                
 
           
            
            
                
            
評論