antvG6的基础使用方法以及制作树形图中的踩坑
一、树形图的生成
项目背景:用父子结构的树形图来展示交换机之间的关系并且处理相关业务逻辑
1.使用antvg6的树形图,首先到官网示例里找到一个和我们想要做的差不多的例子,在此基础上修改
官方教程
1先下载包
npm install --save @antv/g6
2然后导入
import G6 from '@antv/g6';
3创建一个视图容器
<div id="mountNode"></div>
4准备数据
const data = {
// 点集
nodes: [
{
id: 'node1', // String,该节点存在则必须,节点的唯一标识
x: 100, // Number,可选,节点位置的 x 值
y: 200, // Number,可选,节点位置的 y 值
},
{
id: 'node2', // String,该节点存在则必须,节点的唯一标识
x: 300, // Number,可选,节点位置的 x 值
y: 200, // Number,可选,节点位置的 y 值
},
],
// 边集
edges: [
{
source: 'node1', // String,必须,起始点 id
target: 'node2', // String,必须,目标点 id
},
],
};
5实例化创建关系图
const graph = new G6.Graph({
container: 'mountNode', // String | HTMLElement,必须,在 Step 1 中创建的容器 id 或容器本身
width: 800, // Number,必须,图的宽度
height: 500, // Number,必须,图的高度
});
6配置数据源渲染
graph.data(data); // 读取 Step 2 中的数据源到图上
graph.render(); // 渲染图
最终效果
以上就是基本的使用
二、拓扑图项目中遇到的坑
#### 1、增加节点之后要把父节点以下的节点都展示出来
新建接口提交之后要把父节点以下的所有节点都请求回来并且插入到父节点以下,实现此时要重新渲染父节点以下的所有节点并且父节点以上的节点要递归进行修改计数的label
//添加节点
const item = graph.findById(node.pid)//获取父节点
const model = item.getModel()//拿到父节点模型
this.getChildNode(node.pid, model) //重新请求该节点以下所有子节点并渲染
item.update(model) //此api是重点,更新当前节点以下的布局
this.recursion(node.pid, { add: true }) //递归加一上边所有节点
methods:{
/**
* 请求子节点并添加到视图上
* @param {*} id 当前点击节点的id
* @param {*} model 当前节点详情
*/
getChildNode(id, model) {
this.loading = true
topoTree({ id, maxLevel: 2 })
.then(res => {
if (res.code === 200) {
let childrenList = res.data.children
model.children = childrenList //插入子节点
model.collapsed = false //展开节点
graph.updateChild(model, model.id) //更新节点
}
})
.finally(() => {
this.loading = false
})
},
/**
* 递归让父节点加一或者减一
* @param {*} pid 父节点id
* @param {*} isAdd add:true递归加 add:false递归减
*/
recursion(pid, isAdd) {
const parentNode = graph.findById(pid)
const { add } = isAdd
add ? ++parentNode._cfg.model.childrenNum : --parentNode._cfg.model.childrenNum
graph.refreshItem(parentNode) //更新节点
const curPid = parentNode._cfg.model.pid
if (curPid < -1) return
this.recursion(curPid, isAdd)
},
}
这里要查看文档中 的元素实例和方法
---------------------------------------------------------------分割线-----------------------------------------------------------
继续踩坑,新需求,如何让节点下边的label斜着展示
效果如下:
此事需要自定义节点 官方文档 你会发现,没TM的写详情
直接看我写的
首先要调用G6.registerNode配置draw这个函数
G6.registerNode(
'flow-circle',
{
/**绘制大圆点 */
const circle = group.addShape('circle', {
attrs: {
x: 0,
y: 0
},
name: 'big-dot-shape'
})
/**节点lable */
const text = group.addShape('text', {
attrs: {
x: nodeOrigin.x - 20,
y: nodeOrigin.y + 25,
text: name ,
fill: '#000',
textAlign: 'end',
},
name: 'lable-shape'
}).translate(-10, 6)
// 三个顶级节点的文字不用转角度
if (cfg.id !== '-1') {
text.rotate(-0.4) //逆时针旋转0.4
}
},
'circle'
)
如果想更新节点,比如更改节点上的字或者改变节点上的元素,要自定义update函数,才行
update(cfg, node) {
const { label, childrenNum, name } = cfg
// 更新子节点数量
const group = node.getContainer()
const childNumShape = group.find(ele => ele.get('name') === 'childNum-shape')
childNumShape.attrs.text = childrenNum
// 更新所有的label
const nameShape = group.find(ele => ele.get('name') === 'lable-shape')
nameShape.attrs.text = name
this.updateLinkPoints(cfg, group)
},
如果想这只节点状态,也就是鼠标移入高亮,移出变暗效果就要自定义setState函数
setState(name, value, item) {
const group = item.getContainer()
const bigDotShap = group.find(e => e.get('name') === 'big-dot-shape')
if (name === 'highlight') {
bigDotShap.attr({
stroke: 'rgba(95,149,255, 1)',
fill: 'rgba(95,149,255, 1)'
})
} else if (name === 'dark') {
bigDotShap.attr({
stroke: 'rgba(255,117,0, 1)',
fill: 'rgba(255,117,0, 0.9)'
})
}
}