官方文档

官方文档链接(看了之后感觉懂了,但是没完全懂。)

具体用途

业务需求

  • 制作数据亲缘关系大概类似于制作ER图。一开始想用ecarts的拓扑图,但是ecarts有个定位问题一直没搞懂,找不到解决办法。 ecarts的节点需要自定义定位,但是我们是动态数据,力导算法不符合业务需求,所以最终选择了antv g6。

主要问题

1\。需要自定义节点。 g6使用自定义的dom节点来满足修改需求。但是根据文档,dom节点不能使用g6提供的点击事件。

  • 通过配置节点类型,使节点指向用户自定义的节点。

// 高亮当前节点并按类型匹配自定义节点

if (this.data.nodes[i].highLight u003du003d 1) {

this.data.nodes[i].type u003d 'center'

} 其他 {

this.data.nodes[i].type u003d 'dom-node'

}

  • 自定义dom节点

G6.registerNode(

'dom 节点', {

绘制:(cfg,组)u003d> {

// console.log(cfg, group)

常量形状 u003d group.addShape('dom', {

属性:{

宽度:cfg.size[0],

高度:cfg.size[1],

// html 传入 DOM

html:`

<div onclicku003d"select(${cfg.name})" idu003d"${cfg.select}" classu003d"dom-node-style" styleu003d"cursor:pointer;border-radius: 5px;width: ${

cfg.size[0] - 5

}px;高度:${cfg.size[1] - 5}px;显示:弹性;">

<span styleu003d"margin:auto; padding:auto; color: #000">${cfg.id}</span>

</div> `,

},

可拖动:真,

});

返回形状;

},

},

'单节点',

);

// 当前表节点

G6.registerNode(

“中心”,{

绘制:(cfg,组)u003d> {

// 控制台.log(cfg)

常量形状 u003d group.addShape('dom', {

属性:{

宽度:cfg.size[0],

高度:cfg.size[1],

// HTML ${CFG.活跃? "class u003d'selected-style'": "class u003d'node-style'"} 传入 DOM“

html:`

<div onclicku003d"select(${cfg.name})" idu003d"${cfg.select}" classu003d"node-style" styleu003d"width: ${

cfg.size[0] - 5

}px;高度:${cfg.size[1] - 5}px;显示:弹性;边框半径:5px;光标:指针;">

<span styleu003d"margin:auto; padding:auto; color: #000">${cfg.id}</span>

</div> `,

},

可拖动:真,

});

返回形状;

},

},

'单节点',

);

2\。调整状态样式,单击节点或线时更改样式。

  • 默认线路可以直接配置。详见文档

默认边缘:{

风格:{

endArrow:真,

线宽:2,

中风:'#CED4D9',

填写:“#CED4D9”,

},

},

边缘状态样式:{

点击:{

线宽:2,

中风:'#5394ef',

填充:“#5394ef”,

},

},

// 边缘点击事件

graph.on('edge:click', (e) u003d> {

// 首先,将当前处于点击状态的所有边设置为非点击状态

常量 clickEdges u003d graph.findAllByState('edge', 'click');

clickEdges.forEach((ce) u003d> {

graph.setItemState(ce, 'click', false);

});

常量项 u003d e.item; // 获取鼠标输入的边缘元素对象

常量 jobId u003d item._cfg.model.jobId

graph.setItemState(item, 'click', true); // 设置当前边缘的点击状态为true

that.getLineInfo(jobId)

});

  • 自定义dom节点需要动态改变class属性来改变样式。目前还没有找到更好的解决方案。欢迎交流!

// 节点点击事件

让那个 u003d 这个;

window.select u003d 函数(id){

常量 clickEdges u003d graph.findAllByState('edge', 'click');

clickEdges.forEach((ce) u003d> {

graph.setItemState(ce, 'click', false);

});

that.getNodeInfo(id)

var divId u003d 'temp' + id

// 获取当前选中的div,点击这个div替换选中的样式,其他所有div恢复未选中的样式

var selectId u003d document.getElementById(divId)

for(让 i 在 that.data.nodes 中){

if (that.data.nodes[i].name u003du003d id) {

// if (that.data.nodes[i].isActive u003du003d false) {

selectId.setAttribute('class', 'selected-style')

that.data.nodes[i].isActive u003d true

// }

} 其他 {

让 tempId u003d document.getElementById('temp' + that.data.nodes[i].name)

if (that.data.nodes[i].type u003du003d 'dom-node') {

tempId.setAttribute('class', 'dom-node-style')

} 其他 {

tempId.setAttribute('class', 'node-style')

}

that.data.nodes[i].isActive u003d false

}

}

}

3\。如何销毁画布?

  • 在每个数据请求之前进行判断。如果已经有数据,则销毁画布。

// 避免多次渲染数据并销毁画布

if (this.chart !u003du003d '') {

this.chart.destroy()

}

  • 在渲染之前分配这个 g6 chart u003d graph

4\。使用交互模式。默认模式包括单击选定节点并拖动画布的行为。触发时会重新渲染画布,从而取消自定义dom节点设置的状态样式。 (自定义dom节点写在draw中,改变dom节点的状态样式,比如选择后改变颜色,是通过动态改变class属性来实现的)。这个问题目前还没有解决。

5\。对于布局问题,g6也是使用自定义节点位置,但是提供了dagre分层布局,可以满足需求。

布局:{

type: 'dagre', //分层布局

rankdir: 'LR', // 可选的。它默认位于图表的中心

align: 'DL', // 可选

nodeep: 25, // 可选

rankep: 25, // 可选

controlPoints: true, // 可选

},

完整代码

<脚本>

//引入g6

从“@antv/g6”导入 G6;

进口{

获取图形数据,

获取线路信息,

获取节点信息

} 来自'@/api/home/assetCatalogueDetail'

导出默认 {

数据() {

返回{

身份证:0,

type:0,//0-全是近亲,1-直系父子,2-全父表,3-全子表

activeName:'first',

图表:'',

可见:真实,

节点列表:[],

行列表:[],

数据:{

// 点集

节点:[],

// 边集

边缘:[],

}

}

},

方法:{

初始化(ID){

这个.id u003d id

this.getData()

},

获取数据() {

// 避免多次渲染数据并销毁画布

if (this.chart !u003du003d '') {

this.chart.destroy()

}

this.getNodeInfo(this.id)

getGraphData(对象。分配({

basicDataId:this.id,

关系类型:this.type

})).then(响应 u003d> {

this.data.nodes u003d response.data.data.node

this.data.edges u003d response.data.data.line

// console.log(this.data)

for(让 i 在 this.data.nodes 中){

// g6 id 代表节点名

让名称 u003d this.data.nodes[i].name

让 id u003d this.data.nodes[i].id

this.data.nodes[i].id u003d 名称

this.data.nodes[i].name u003d id

// 设置节点的连接点。 anchorPoint是指与节点相连的边的相对位置,即节点与其相关边的交点位置

this.data.nodes[in].anchor Points u003d [

[0.5, 0],

[1, 0.5],

[0, 0.5],

[0.5, 1],

]

this.data.nodes[i].select u003d 'temp' + id

this.data.nodes[i].isActive u003d false

this.data.nodes[i].size u003d [120, 40]

// 高亮当前节点并按类型匹配自定义节点

if (this.data.nodes[i].highLight u003du003d 1) {

this.data.nodes[i].type u003d 'center'

} 其他 {

this.data.nodes[i].type u003d 'dom-node'

}

}

this.renderView()

})

},

渲染视图() {

G6.registerNode(

'dom 节点', {

绘制:(cfg,组)u003d> {

// console.log(cfg, group)

常量形状 u003d group.addShape('dom', {

属性:{

宽度:cfg.size[0],

高度:cfg.size[1],

// html 传入 DOM

html:`

<div onclicku003d"select(${cfg.name})" idu003d"${cfg.select}" classu003d"dom-node-style" styleu003d"cursor:pointer;border-radius: 5px;width: ${

cfg.size[0] - 5

}px;高度:${cfg.size[1] - 5}px;显示:弹性;">

<span styleu003d"margin:auto; padding:auto; color: #000">${cfg.id}</span>

</div> `,

},

可拖动:真,

});

返回形状;

},

},

'单节点',

);

// 当前表节点

G6.registerNode(

“中心”,{

绘制:(cfg,组)u003d> {

// 控制台.log(cfg)

常量形状 u003d group.addShape('dom', {

属性:{

宽度:cfg.size[0],

高度:cfg.size[1],

// HTML ${CFG.活跃? "class u003d'selected-style'": "class u003d'node-style'"} 传入 DOM“

html:`

<div onclicku003d"select(${cfg.name})" idu003d"${cfg.select}" classu003d"node-style" styleu003d"width: ${

cfg.size[0] - 5

}px;高度:${cfg.size[1] - 5}px;显示:弹性;边框半径:5px;光标:指针;">

<span styleu003d"margin:auto; padding:auto; color: #000">${cfg.id}</span>

</div> `,

},

可拖动:真,

});

返回形状;

},

},

'单节点',

);

常量图 u003d 新 G6.Graph({

renderer: 'svg', //使用Dom节点时,需要使用svg来渲染情况

容器:'mountNode',

宽度:800,

高度:500,

布局:{

type: 'dagre', //分层布局

rankdir: 'LR', // 可选的。它默认位于图表的中心

align: 'DL', // 可选

nodeep: 25, // 可选

rankep: 25, // 可选

controlPoints: true, // 可选

},

默认边缘:{

风格:{

endArrow:真,

线宽:2,

中风:'#CED4D9',

填写:“#CED4D9”,

// 光标:'指针'

},

},

边缘状态样式:{

点击:{

线宽:2,

中风:'#5394ef',

填充:“#5394ef”,

},

},

模式:{

默认值:[

// 'drag canvas', // 拖动画布

// '缩放画布', // 缩放画布

]

},

fitCenter: true, //平移到中心对齐到画布的中心,但不缩放

});

// 节点点击事件

让那个 u003d 这个;

window.select u003d 函数(id){

常量 clickEdges u003d graph.findAllByState('edge', 'click');

clickEdges.forEach((ce) u003d> {

graph.setItemState(ce, 'click', false);

});

that.getNodeInfo(id)

var divId u003d 'temp' + id

// 获取当前选中的div,点击这个div替换选中的样式,其他所有div恢复未选中的样式

var selectId u003d document.getElementById(divId)

for(让 i 在 that.data.nodes 中){

if (that.data.nodes[i].name u003du003d id) {

// if (that.data.nodes[i].isActive u003du003d false) {

selectId.setAttribute('class', 'selected-style')

that.data.nodes[i].isActive u003d true

// }

} 其他 {

让 tempId u003d document.getElementById('temp' + that.data.nodes[i].name)

if (that.data.nodes[i].type u003du003d 'dom-node') {

tempId.setAttribute('class', 'dom-node-style')

} 其他 {

tempId.setAttribute('class', 'node-style')

}

that.data.nodes[i].isActive u003d false

}

}

}

// 边缘点击事件

graph.on('edge:click', (e) u003d> {

// 首先,将当前处于点击状态的所有边设置为非点击状态

常量 clickEdges u003d graph.findAllByState('edge', 'click');

clickEdges.forEach((ce) u003d> {

graph.setItemState(ce, 'click', false);

});

常量项 u003d e.item; // 获取鼠标输入的边缘元素对象

常量 jobId u003d item._cfg.model.jobId

graph.setItemState(item, 'click', true); // 设置当前边缘的点击状态为true

that.getLineInfo(jobId)

});

this.chart u003d 图

图形.data(this.data); // 将步骤2中的数据源读取到图表中

图.render(); // 渲染

// graph.fitView();

},

获取节点信息(值){

this.visible u003d true

获取节点信息(对象。分配({

id:值,

curId:this.id

})).then(响应 u003d> {

this.nodeList u003d response.data.data

// console.log(this.nodeList)

})

},

getLineInfo(值) {

this.visible u003d false

getLineInfo(值).then(响应 u003d> {

this.lineList u003d response.data.data

// console.log(this.lineList)

})

},

}

}

</脚本>

<样式>

.node 样式 {

背景颜色:#fff;

边框:1px 实心#5B8FF9;

}

.selected-style {

背景色:橙色;

}

.dom 节点样式 {

背景颜色:#fff;

边框:1px 实心#000;

}

</style>

Logo

前往低代码交流专区

更多推荐