介绍
基于Relation-graph,实现多父级,子级多对一,自定义坐标,一键展开,导出PDF,过滤等。
1、VUE使用
## npm 下载
npm install --save relation-graph
## yarn 下载
yarn add relation-graph
import RelationGraph from "relation-graph";
<RelationGraph
id="appc"
ref="seeksRelationGraph"
:options="graphOptions"
:on-node-click="onNodeClick"
:on-line-click="onLineClick"
:on-node-expand="onNodeExpand"
/>
graphOptions: {
allowShowMiniToolBar: true, //不显示工具栏
layouts: [
{
label: "中心",
layoutName: "tree", //布局方式(tree树状布局/center中心布局/force自动布局)
layoutClassName: "seeks-layout-center",
defaultJunctionPoint: "border", //默认的连线与节点接触的方式
defaultNodeShape: 1, //默认的节点形状,0:圆形;1:矩形
defaultLineShape: 1, //默认的线条样式(1:直线/2:样式2/3:样式3/4:折线/5:样式5/6:样式6)
allowShowMiniToolBar: false, // 是否显示工具栏
allowShowDownloadButton: false,
centerOffset_x: 100,
centerOffset_y: 150,
// 通过这4个属性来调整 tree-层级距离&节点距离
max_per_width: "200", //节点距离限制:节点之间横向距离最大值
min_per_height: undefined, //节点距离限制:节点之间纵向距离最小值
max_per_height: "150", //节点距离限制:节点之间纵向距离最大值
min_per_width: undefined, //节点距离限制:节点之间横向距离最小值
levelDistance: "", // 如果此选项有值,则优先级高于上面那4个选项
},
],
downloadImageFileName: '',
defaultNodeShape: 1, //默认的节点形状,0:圆形;1:矩形
defaultExpandHolderPosition: "bottom", //节点展开关闭的按钮位置
defaultLineShape: 5, //默认的线条样式(1:直线/2:样式2/3:样式3/4:折线/5:样式5/6:样式6)
defaultJunctionPoint: "tb", //默认的连线与节点接触的方式(border:边缘/ltrb:上下左右/tb:上下/lr:左右)当布局为树状布局时应使用tb或者lr,这样才会好看
defaultNodeBorderWidth: 0.2, //节点边框粗细
defaultLineColor: "rgba(0, 186, 189, 1)", //默认的线条颜色
defaultNodeColor: "rgba(0, 206, 209, 1)", //默认的节点背景颜色
defaultNodeWidth: "100", //节点宽度
defaultNodeHeight: "50", //节点高度
defaultFocusRootNode: false, //默认为根节点添加一个被选中的样式
moveToCenterWhenResize: true, //当图谱的大小发生变化时,是否重新让图谱的内容看起来居中
},
2、节点方法
// 节点数据
const data = res.data;
// 跟节点信息
this.rootNode = {id: data.id, text: data.name,fixed: true, x: (data.children.length*160 ) / 2, y:50, data: {shareholdingId: data.shareholdingId, name: data.name}, width: 350, height: 30};
// 子节点集合
let sonChildren = data.children;
// 父节点集合
let parents = data.parents;
if (sonChildren && sonChildren.length > 0) await this.forSonChildren(data.id,sonChildren,1);
if (parents && parents.length > 0) await this.forParents(data.id,parents);
let xObj = {};
// 遍历所有节点自定义坐标
this.nodes.forEach((item,index) => {
// level为节点层级
let level = item.data.level;
if (level) {
item.fixed = true;
item.y = level *300;
item.x = (xObj[`x${level}`] || 0) + 160 - level*70;
xObj[`x${level}`] = (xObj[`x${level}`] || 0) + 160;
}
})
_this.showSeeksGraph(data.id,this.nodes,this.links);
3、节点递归处理
forSonChildren(par, children, i) {
children.forEach(ele => {
let toId = ele.id
// 判断是否存在相同节点
let linksitem =[];
if( this.links.length > 0){
linksitem = this.links.filter(f => f.data.shareholdingId == ele.shareholdingId)
}
if (linksitem.length > 0) {
// 存储旧的节点ID
let odlNodeId = linksitem[0].to
let fin = this.nodes.findIndex(f => f.id == odlNodeId)
// 根据层级判断是否更换原节点
if (this.nodes[fin].data.level >= i) {
this.nodes.splice(fin, 1)
toId = this.nodes[fin].id
} else {
this.nodes.splice(fin, 1)
this.links.forEach(item => {
if (item.data.shareholdingId == ele.shareholdingId) {
item.to = toId
}
if (item.from == odlNodeId) {
item.from = toId
}
})
}
}
this.nodes.push({ id: toId, text: ele.name, data: {shareholdingId: ele.shareholdingId, name: ele.name, level: i}, color: "#43a2f1", fontColor: "yellow", width: 150, height: 60 },)
this.links.push({ from: par, to: toId, data: {shareholdingId: ele.shareholdingId}, text: `${ele.percent}%`, color: "#43a2f1" })
if (ele.children && ele.children.length > 0) {
this.forSonChildren(ele.id, ele.children, i+1)
}
})
},
forParents(son, parents) {
parents.forEach(ele => {
this.links.push({ from: ele.id, to: son, text: `${ele.percent}%`, color: "#43a2f1", })
this.nodes.push({ id: ele.id, text: ele.name, data: {shareholdingId: ele.shareholdingId,name: ele.name,}, color: "#43a2f1", fontColor: "yellow", width: 150, height: 60 },)
if (ele.parents && ele.parents.length > 0) {
this.forParents(ele.id, ele.forParents)
}
})
},
4、渲染
showSeeksGraph(id, nodes, links) {
// 层级过滤
let nodeArr = nodes.filter(f => f.data.level == 1)
let nodePar = nodes.filter(f => !f.data.level)
nodeArr.forEach(ele => {
ele.data.isNeedLoadDataFromRemoteServer = true
ele.data.childrenLoaded = false
if (links.filter(f => f.from == ele.id).length) {
ele.expandHolderPosition = 'bottom';
ele.expanded = false;
}
})
var __graph_json_data = {
rootId: id,
nodes: [
this.rootNode,
...nodeArr,
...nodePar
],
links: [
...links
],
};
this.setGraphData(__graph_json_data)
},
setGraphData(jsonData) {
var jsonList = jsonData;
jsonList.nodes.forEach((thisNode) => {
if (thisNode.id === 'a') {
thisNode.width = 200;
thisNode.height = 60;
thisNode.offset_x = -20; // 调整x偏移,让根节点看起来更居中
// thisNode.offset_y = 40; // 调整x偏移,让根节点看起来更居中
}
});
setTimeout(() => {
this.g_loading = false;
this.$refs.seeksRelationGraph.setJsonData(jsonList, (graphInstance) => {
// 这些写上当图谱初始化完成后需要执行的代码
});
}, 1000);
},