G6 图可视化引擎——入门教程——元素及其配置
圖的元素特指圖上的節(jié)點(diǎn) Node 和邊 Edge 。在上一章節(jié)中,我們已經(jīng)將 Tutorial 案例的圖繪制了出來(lái),但是各個(gè)元素及其 label 在視覺(jué)上很簡(jiǎn)陋。本文通過(guò)將上一章節(jié)中簡(jiǎn)陋的元素美化成如下效果,介紹元素的屬性、配置方法。
基本概念
圖的元素
圖的元素特指圖上的節(jié)點(diǎn) Node 和邊 Edge 。G6 內(nèi)置了一系列 內(nèi)置的節(jié)點(diǎn) 和 內(nèi)置的邊,供用戶自由選擇。G6 不同的內(nèi)置節(jié)點(diǎn)或不同的內(nèi)置邊主要區(qū)別在于元素的 圖形 Shape,例如,節(jié)點(diǎn)可以是圓形、矩形、圖片等。
元素的屬性
不論是節(jié)點(diǎn)還是邊,它們的屬性分為兩種:
- 樣式屬性 style:對(duì)應(yīng) Canvas 中的各種樣式,在元素狀態(tài) State 發(fā)生變化時(shí),可以被改變;
- 其他屬性:例如圖形類型( type)、id(id )一類在元素狀態(tài) State 發(fā)生變化時(shí)不能被改變的屬性。
例如,G6 設(shè)定 hover 或 click 節(jié)點(diǎn),造成節(jié)點(diǎn)狀態(tài)的改變,只能自動(dòng)改變節(jié)點(diǎn)的樣式屬性(如 fill、stroke 等),其他屬性(如 type 等)不能被改變。如果需要改變其他屬性,要通過(guò) graph.updateItem 手動(dòng)配置。樣式屬性是一個(gè)名為 style 的對(duì)象, style 字段與其他屬性并行。
數(shù)據(jù)結(jié)構(gòu)
以節(jié)點(diǎn)元素為例,其屬性的數(shù)據(jù)結(jié)構(gòu)如下:
{id: 'node0', // 元素的 idtype: 'circle', // 元素的圖形size: 40, // 元素的大小label: 'node0' // 標(biāo)簽文字labelCfg: { // 標(biāo)簽配置屬性positions: 'center',// 標(biāo)簽的屬性,標(biāo)簽在元素中的位置style: { // 包裹標(biāo)簽樣式屬性的字段 style 與標(biāo)簽其他屬性在數(shù)據(jù)結(jié)構(gòu)上并行fontSize: 12 // 標(biāo)簽的樣式屬性,文字字體大小// ... // 標(biāo)簽的其他樣式屬性}}// ..., // 其他屬性style: { // 包裹樣式屬性的字段 style 與其他屬性在數(shù)據(jù)結(jié)構(gòu)上并行fill: '#000', // 樣式屬性,元素的填充色stroke: '#888', // 樣式屬性,元素的描邊色// ... // 其他樣式屬性} }邊元素的屬性數(shù)據(jù)結(jié)構(gòu)與節(jié)點(diǎn)元素相似,只是其他屬性中多了 source 和 target 字段,代表起始和終止節(jié)點(diǎn)的 id。
細(xì)化在圖 1 中 Tutorial 案例 的視覺(jué)需求,我們需要完成:
- 視覺(jué)效果:
- R1: 節(jié)點(diǎn)的描邊和填充色,對(duì)應(yīng)節(jié)點(diǎn)樣式屬性:fill,stroke;
- R2: 節(jié)點(diǎn)上標(biāo)簽文本的顏色,對(duì)應(yīng)節(jié)點(diǎn)其他屬性:labelCfg;
- R3: 邊的透明度和顏色,對(duì)應(yīng)邊樣式屬性:opacity,stroke;
- R4: 邊上標(biāo)簽文本的方向和顏色,對(duì)應(yīng)邊其他屬性:labelCfg;
- 數(shù)據(jù)與視覺(jué)映射:
- R5: 根據(jù)數(shù)據(jù)中節(jié)點(diǎn)的 class 屬性映射節(jié)點(diǎn)的形狀,對(duì)應(yīng)節(jié)點(diǎn)其他屬性:type;
- R6: 根據(jù)數(shù)據(jù)中邊的 weight 屬性映射邊的粗細(xì),對(duì)應(yīng)邊樣式屬性:lineWidth。
配置屬性
在 G6 中,根據(jù)不同的場(chǎng)景需求,有 7 種配置元素屬性的方式。這里,我們簡(jiǎn)單介紹其中的兩種:
1. 實(shí)例化圖時(shí)全局配置
適用場(chǎng)景:所有節(jié)點(diǎn)統(tǒng)一的屬性配置,所有邊統(tǒng)一的屬性配置。
使用方式:使用圖的兩個(gè)配置項(xiàng):
- defaultNode:節(jié)點(diǎn)在默認(rèn)狀態(tài)下的樣式屬性(style)和其他屬性;
- defaultEdge:邊在默認(rèn)狀態(tài)下的樣式屬性(style)和其他屬性。
?? 注意: 由于是統(tǒng)一的配置,不能根據(jù)數(shù)據(jù)中的屬性(如 class、weight)等值的不同進(jìn)行個(gè)性化設(shè)置,因此只能滿足 R1、R2、R3、R4 需求。達(dá)到如下效果:
通過(guò)如下方式在實(shí)例化圖時(shí) defaultNode 和 defaultEdge ,可以完成上圖效果:
const graph = new G6.Graph({// ... // 圖的其他配置// 節(jié)點(diǎn)在默認(rèn)狀態(tài)下的樣式配置(style)和其他配置defaultNode: {size: 30, // 節(jié)點(diǎn)大小// ... // 節(jié)點(diǎn)的其他配置// 節(jié)點(diǎn)樣式配置style: {fill: 'steelblue', // 節(jié)點(diǎn)填充色stroke: '#666', // 節(jié)點(diǎn)描邊色lineWidth: 1, // 節(jié)點(diǎn)描邊粗細(xì)},// 節(jié)點(diǎn)上的標(biāo)簽文本配置labelCfg: {// 節(jié)點(diǎn)上的標(biāo)簽文本樣式配置style: {fill: '#fff', // 節(jié)點(diǎn)標(biāo)簽文字顏色},},},// 邊在默認(rèn)狀態(tài)下的樣式配置(style)和其他配置defaultEdge: {// ... // 邊的其他配置// 邊樣式配置style: {opacity: 0.6, // 邊透明度stroke: 'grey', // 邊描邊顏色},// 邊上的標(biāo)簽文本配置labelCfg: {autoRotate: true, // 邊上的標(biāo)簽文本根據(jù)邊的方向旋轉(zhuǎn)},}, });2. 在數(shù)據(jù)中配置
適用場(chǎng)景:不同節(jié)點(diǎn)/邊可以有不同的個(gè)性化配置。
因此,這種配置方式可以滿足 R5、R6 需求。
使用方式:可以直接將配置寫入數(shù)據(jù)文件;也可以在讀入數(shù)據(jù)后,通過(guò)遍歷的方式寫入配置。這里展示讀入數(shù)據(jù)后,通過(guò)遍歷的方式寫入配置。下面代碼展示了如何遍歷數(shù)據(jù)進(jìn)行屬性的配置:
const nodes = remoteData.nodes; nodes.forEach(node => {if (!node.style) {node.style = {};}switch (node.class // 根據(jù)節(jié)點(diǎn)數(shù)據(jù)中的 class 屬性配置圖形) {case 'c0': {node.type = 'circle'; // class = 'c0' 時(shí)節(jié)點(diǎn)圖形為 circlebreak;}case 'c1': {node.type = 'rect'; // class = 'c1' 時(shí)節(jié)點(diǎn)圖形為 rectnode.size = [35, 20]; // class = 'c1' 時(shí)節(jié)點(diǎn)大小break;}case 'c2': {node.type = 'ellipse'; // class = 'c2' 時(shí)節(jié)點(diǎn)圖形為 ellipsenode.size = [35, 20]; // class = 'c2' 時(shí)節(jié)點(diǎn)大小break;}} });graph.data(remoteData);運(yùn)行結(jié)果如下:
可以看到,圖中有一些節(jié)點(diǎn)被渲染成了矩形,還有一些被渲染成了橢圓形。除了設(shè)置 type 屬性之外,我們還覆蓋了上文全局配置的節(jié)點(diǎn)的 size 屬性,在矩形和橢圓的情況下,size 是一個(gè)數(shù)組;而在默認(rèn)圓形的情況下,G6 將仍然讀取全局配置的 size 屬性為數(shù)字 30。也就是說(shuō),動(dòng)態(tài)配置屬性讓我們既可以根據(jù)數(shù)據(jù)的不同配置不同的屬性值,也可以有能力覆蓋全局靜態(tài)的屬性值。
進(jìn)一步地,我們嘗試根據(jù)數(shù)據(jù)的比重不同,配置不一樣邊的粗細(xì):
// const nodes = ...// 遍歷邊數(shù)據(jù) const edges = remoteData.edges; edges.forEach(edge => {if (!edge.style) {edge.style = {};}edge.style.lineWidth = edge.weight; // 邊的粗細(xì)映射邊數(shù)據(jù)中的 weight 屬性數(shù)值 });graph.data(remoteData);結(jié)果如下:
如圖所示,邊的粗細(xì)已經(jīng)按照數(shù)據(jù)的比重成功渲染了出來(lái),但是邊原有的樣式(透明度、顏色)卻丟失了。這是因?yàn)槲覀兲岬竭^(guò)動(dòng)態(tài)配置屬性會(huì)覆蓋全局配置屬性,這里配置了 style.lineWidth,導(dǎo)致覆蓋了全局的 style 對(duì)象。解決辦法是將被覆蓋的邊的樣式都移到動(dòng)態(tài)配置里面來(lái):
完整代碼
至此,完整代碼如下:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8" /><title>Tutorial Demo</title> </head> <body> <div id="mountNode"></div> <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.1.0/build/g6.js"></script> <script>const graph = new G6.Graph({container: 'mountNode',width: 800,height: 600,fitView: true,fitViewPadding: [20, 40, 50, 20],defaultNode: {size: 30,labelCfg: {style: {fill: '#fff',},},},defaultEdge: {labelCfg: {autoRotate: true,},},});const main = async () => {const response = await fetch('https://gw.alipayobjects.com/os/basement_prod/6cae02ab-4c29-44b2-b1fd-4005688febcb.json',);const remoteData = await response.json();const nodes = remoteData.nodes;const edges = remoteData.edges;nodes.forEach(node => {if (!node.style) {node.style = {};}node.style.lineWidth = 1;node.style.stroke = '#666';node.style.fill = 'steelblue';switch (node.class) {case 'c0': {node.type = 'circle';break;}case 'c1': {node.type = 'rect';node.size = [35, 20];break;}case 'c2': {node.type = 'ellipse';node.size = [35, 20];break;}}});edges.forEach(edge => {if (!edge.style) {edge.style = {};}edge.style.lineWidth = edge.weight;edge.style.opacity = 0.6;edge.style.stroke = 'grey';});graph.data(remoteData);graph.render();};main(); </script> </body> </html>總結(jié)
以上是生活随笔為你收集整理的G6 图可视化引擎——入门教程——元素及其配置的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 16. 3Sum Closest 最接近
- 下一篇: G6 图可视化引擎——入门教程——使用图