使用antV-G6在angualr中画树形关系图(流量追踪图)
公司有个需求就是既要呈现出每个节点之间的关系(图里面需要带箭头,为了表现出流向关系),又要排版呈现出树状结构,也就是说是具备层次关系的,这种图呢就相当于既不完全是树图,形状呢又不是关系图,我算是苦思冥想了。而且又是在angualr中,angualr中支持的第三方插件特别少,本来想采用echarts的树状图,但是发现,树图的每个节点不能有两个父节点,也就是说两个节点不能同时指向一个节点,后来就放弃了,接着我想采用echarts里面的关系图,但是发现关系图需要自己去定义每一个节点的坐标,这对于我们公司的需求有很多节点的情况下,是完全不可能实现的,后来引用了antV的G6,加上自己本身的一些构思,实现了以下效果:
在angualr的你需要放入该图的组件的ts文件中的开头,需要加上以下两句话,insertCss可以先不写,这个是为了后面显示提示框而导入的,如果需要的话就安装(npm install insert-css)并导入,不需要可以省略。
import G6 from '@antv/g6'; // npm install --save @antv/g6 先安装后引入啊!!!
import insertCss from 'insert-css'; //npm install insert-css 先安装后引入啊!!!
首先定义一个全局变量的data,用于存放流程图的节点和边
data = {
// 点集
nodes: [],
// 边集
edges: [],
};
然后是html结构
<div class="tracing_right">
<div id="mountNode" style="width: 98%;height:100%;margin: 0 auto;overflow-x: scroll;overflow-y: scroll"></div>
</div>
然后需要定义一个render函数,当然可以随意取函数的名称,这里面的代码大多是参考G6里面的示例代码https://g6.antv.vision/zh/examples/net/dagreFlow#lrDagre,参数说明如下:
render(){
//这个是用于定义我图中的提示框,就是气泡的样式
insertCss(`
.g6-tooltip {
border: 1px solid #8962FD;
border-radius: 4px;
font-size: 12px;
color: #8962FD;
background-color: rgba(255, 255, 255, 0.8);
padding: 10px 8px;
box-shadow: rgb(219, 208, 254) 0px 0px 10px;
width:180px;
height:60px;
position:absolute;
left:-100px;
top:100px
}
`);
const width = document.getElementById('mountNode').scrollWidth;
const height = document.getElementById('mountNode').scrollHeight || 500;
const graph = new G6.Graph({
container: 'mountNode',
width,
height,
fitView: true, //设置是否将图充满整个画布
modes: {
//这个是设置默认节点和默认边的地方,'zoom-canvas'这个参数的作用是可以对图进行鼠标滚动放大缩小,根据需求添加
default: ['drag-canvas', 'drag-node','zoom-canvas',
//下面这个对象是设置提示框的显示内容,我用的是模板字符串显示的
{
type: 'tooltip',
//formatText这个函数的参数model代表的就是传入的每个节点的信息,包括名称之类的信息,在模板字符串中可以通过${model.参数名}去访问每个节点的信息,从而在提示框中显示
formatText: function formatText(model) {
const text =`
<p style="width:180px;height:30px;float:left;line-height:30px;border-bottom:2px dashed rgba(219, 208, 254)">存活个数/总个数:${model.label}</p>
`+'</br>'+`
<p style="width:180px;height:30px;float:left;line-height:30px;">请求次数:${model.label}</p>
`+'</br>';
return text;
},
},],
},
layout: {
type: 'dagre',
rankdir: 'LR',
align: 'DL',
nodesepFunc: () => 3, //这个就是节点与节点之间的距离,可以说是纵向拉伸高度
ranksepFunc: () => 30,//这个参数设置的是你的箭头距离节点的距离,值越大,图横向拉伸的越宽
},
defaultNode: {
size: [30, 20],//节点的大小设置,宽高
type: 'rect', //节点类型,rect就是长方形,还有圆形,菱形等,官网里有,也可以自定义
},
defaultEdge: {
size: 1,
// type: 'line-growth',这个是自定义了边的动画,但是我没使用
color: '#e2e2e2', //边的颜色
style: {
endArrow: { //设置边的末端箭头的样式,如果不需要箭头,不设置即可
path: 'M 0,0 L 8,4 L 8,-4 Z',
fill: '#e2e2e2'
},
},
labelCfg: {
autoRotate: true, //设置边上面的标签的样式
refY: 8, //边标签的文字与边的距离
style: {
fontSize:10, //设置边标签的字体大小
},
},
},
});
graph.clear(); //后面三行照常复制粘贴即可
graph.data(this.data);
graph.render();
}
// 第一次加载获取结构图,这个是我设置的点击事件,我们公司需求就是点击按钮触发流程图的加载
getStructureData=(minServiceName)=>{
var self = this
var m = 300
var n = 300
self.data = {nodes:[],edges :[]}
self.pingArr = []
console.log(self.data)
self.ajax.getAjax("/management/kiali/graph","post",{"namespace":minServiceName},function(data){ //这个是我调用的接口,你们可以直接按照官网上的案例,在开头定义死数据,进行测试,我对接口里面数据的处理,你们可以不看
console.log(data)
for(var i=0;i<data.length;i++){
self.pingData = {}
self.pingData["id"] = data[i].data.id
self.pingData["parentId"] = data[i].data.parentId
self.pingData["name"] = data[i].data.name
self.pingData["color"] = data[i].data.color
self.pingData["nodeType"] = data[i].data.nodeType
self.pingData["responseTime"] = data[i].data.responseTime
self.pingArr.push(self.pingData)
}
console.log(self.pingArr)
//下面就是我掉完接口之后拿到的数据进行遍历,然后往直前定义的节点和边的数组中塞
for(var i=0;i<self.pingArr.length;i++){
if(self.pingArr[i].nodeType == "version"){ //我是对节点类型进行了判断,不同类型的节点,设置节点的颜色不一样,就如图中两种节点
self.data.nodes.push(
{
id: self.pingArr[i]["id"],
label: self.pingArr[i]["name"],
description: 'This is node-1.',
style:{ //这个style就是专门设置节点的样式的
width: 48,
height: 18,
radius: 10,
stroke: '#8962FD', //节点边框颜色
fill: '#8962FD', //节点背景色
lineWidth:5, //边框宽度
strokeOpacity:0.3, //边框透明度
},
labelCfg: { //这个就是节点里面文字的样式设置
style: {
fill: '#fff',
fontSize: 10,
},
position: 'center',
},
},
)
}else if(self.pingArr[i].nodeType == "service"){
//这里如上,如果不区分节点的话可以忽略
self.data.nodes.push(
{
id: self.pingArr[i]["id"],
label: self.pingArr[i]["name"],
description: 'This is node-1.',
style: {
width: 60,
height: 25,
radius: 10,
stroke: '#8962FD',
fill: '#fff',
lineWidth:1.5,
strokeOpacity:0.6
},
labelCfg: {
style: {
fill: '#8962FD',
fontSize: 10,
},
position: 'center',
},
},
)
}
//下面是我放入边的循环结构
if(self.pingArr[i]["parentId"].length>=1){
for(var j=0;j<self.pingArr[i]["parentId"].length;j++){
self.data.edges.push(
{
source: self.pingArr[i]["parentId"][j],
target: self.pingArr[i]["id"],
// label: self.pingArr[i]["responseTime"],
label: '30ms', //这个就是边上面显示的标签的内容,我写死的
color: self.pingArr[i]["color"], //设置边的颜色
style: { //设置边的箭头的样式,如果不需要箭头,这个endArrow可以不写
endArrow: {
path: 'M 0,0 L 8,4 L 8,-4 Z',
fill: self.pingArr[i]["color"],
},
},
},
)
}
}
}
setTimeout( ()=>{
self.render()
},100) //这里就是调用之前定义好的render渲染函数,上面掉接口之后放入数据之后,必须要重新调用render函数去渲染画布的,不然不显示,这里我延时了100ms再调用render函数的原因就是防止加载的时候出现dom无定义的情况,必须要加上延时器。
})
}
这两天写关系图,对antv的G6有了不少的了解,但是我百度搜索一些关于G6的东西的时候,发现几乎没有,可能还是用的少吧,因此,我写了这个博客,欢迎大家参考G6的使用方法,它还是挺好用的!!!!
还有一种是节点可增删改的树形结构图,vue写的,可参考一下:
https://blog.csdn.net/qq_41579104/article/details/113388616
效果是这样:
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/149611.html