应用场景
在做组织关系图时,经常会遇到关系图的实现要求,就是要将人与人或者组织与组织或者人与组织之间的关系进行一一展示。已知的就是节点和关系。
需求分析
最近在写后台管理系统时,遇到一个需求,就是要实现关系图:
如下图所示:
在前年写天眼查功能时,我也遇到过这种需求,不过当时不知道可以用插件来实现,因此功能并未完全开发:
代码实现
直接上代码:
1.安装
1.1 Npm 方式
npm i relation-graph
1.2 Yarn方式
yarn add relation-graph
2.使用
2.1 html部分代码
<template><div><div style="height:calc(100vh - 50px);"><RelationGraph ref="seeksRelationGraph":options="graphOptions":on-node-click="onNodeClick":on-line-click="onLineClick"/></div></div></template>
2.2 script部分代码
<script>import RelationGraph from'relation-graph';//引入插件exportdefault{name:'Demo',components:{ RelationGraph },//注册插件data(){return{//设置插件的参数graphOptions:{allowSwitchLineShape:true,allowSwitchJunctionPoint:true,defaultJunctionPoint:'border'// 这里可以参考"Graph 图谱"中的参数进行设置:http://relation-graph.com/#/docs/graph}}},mounted(){this.showSeeksGraph()},methods:{showSeeksGraph(){//需要指定 节点参数和连接线的参数var __graph_json_data ={rootId:'a',nodes:[// node配置选项:http://relation-graph.com/#/docs/node// node支持通过插槽slot完全自定义,示例:http://relation-graph.com/#/demo/adv-slot{id:'a',text:'A',borderColor:'yellow'},{id:'b',text:'B',color:'#43a2f1',fontColor:'yellow'},{id:'c',text:'C',nodeShape:1,width:80,height:60},{id:'e',text:'E',nodeShape:0,width:150,height:150}],lines:[// link配置选项:http://relation-graph.com/#/docs/link{from:'a',to:'b',text:'关系1',color:'#43a2f1'},{from:'a',to:'c',text:'关系2'},{from:'a',to:'e',text:'关系3'},{from:'b',to:'e',color:'#67C23A'}]}this.$refs.seeksRelationGraph.setJsonData(__graph_json_data,(seeksRGGraph)=>{// Called when the relation-graph is completed })},onNodeClick(nodeObject, $event){
console.log('onNodeClick:', nodeObject)},onLineClick(linkObject, $event){
console.log('onLineClick:', linkObject)}}}</script>
3.如果要需要展示鼠标移入后展示节点细节,则可以用下面的方式
3.1 html部分代码
<template><a-spin :spinning="loading"><div
style="height: calc(100vh - 130px); border: 1px solid #ebebeb"
ref="myPage"><RelationGraph
ref="seeksRelationGraph":options="graphOptions":on-node-click="onNodeClick":on-line-click="onLineClick"><div
slot="node"
slot-scope="{ node }"
style="height: 100%"
@mouseover="showNodeTips(node, $event)"
@mouseout="hideNodeTips(node, $event)"><div
style="
border-radius:50%;cursor: pointer;
word-break:break-all;display: flex;
justify-content: center;
align-items: center;color: #fff;height:100%;
font-size: 12px;overflow: hidden;
"
>{{
node.text &&
node.text
.replace('https://www.','').replace('http://www.','').replace('.com','').replace('.html','').split('/').length >1? node.text
.replace('https://www.','').replace('http://www.','').replace('.com','').replace('.html','').split('/')[
node.text
.replace('https://www.','').replace('http://www.','').replace('.com','').replace('.html','').split('/').length -1]||node.text
.replace('https://www.','').replace('http://www.','').replace('.com','').replace('.html','').split('/')[
node.text
.replace('https://www.','').replace('http://www.','').replace('.com','').replace('.html','').split('/').length -2]: node.text
}}</div></div><!--<div
slot="bottomPanel"
style="
border-top: #efefef solid 1px;height: 60px;
line-height: 60px;
text-align: center;
font-size: 18px;
background-color: #ffffff;
"
>
这里是底部插槽 slot="bottomPanel",可以自定义这里的内容
</div>--></RelationGraph></div><div
v-if="isShowNodeTipsPanel":style="{left: nodeMenuPanelPosition.x +'px',top: nodeMenuPanelPosition.y +'px',}"
style="
z-index:999;padding: 10px;
background-color: #ffffff;border: #eeeeee solid 1px;
box-shadow: 0px 0px 8px #cccccc;position: absolute;
"
><div
style="
line-height: 25px;
padding-left: 10px;color: #888888;
font-size: 12px;
"
>
节点名称:{{ currentNode.text }}</div></div></a-spin></template>
3.2 js部分代码
<script>import RelationGraph from'relation-graph';import{ getRelationship }from'@/services/statistics';//我这边的接口地址,需要改成你自己的exportdefault{components:{ RelationGraph },data(){return{loading:false,data:[],activeKey:'',src:'',isShowCodePanel:false,isShowNodeTipsPanel:false,nodeMenuPanelPosition:{x:0,y:0},currentNode:{},graphOptions:{allowSwitchLineShape:true,allowSwitchJunctionPoint:true,layouts:[{label:'中心',layoutName:'force',//布局方式(tree树状布局/center中心布局/force自动布局)layoutClassName:'seeks-layout-center',//当使用这个布局时,会将此样式添加到图谱上defaultJunctionPoint:'border',//默认的连线与节点接触的方式defaultNodeShape:0,//默认的节点形状,0:圆形;1:矩形defaultLineShape:1,//默认的线条样式(1:直线/2:样式2/3:样式3/4:折线/5:样式5/6:样式6)centerOffset_y:130,//根节点y坐标偏移量(针对项目配置单位为px)min_per_width:150,//节点距离限制:节点之间横向距离最小值min_per_height:180,//节点距离限制:节点之间纵向距离最小值},],defaultNodeShape:0,//默认的节点形状,0:圆形;1:矩形defaultExpandHolderPosition:'bottom',//节点展开关闭的按钮位置defaultLineShape:1,//默认的线条样式(1:直线/2:样式2/3:样式3/4:折线/5:样式5/6:样式6)defaultJunctionPoint:'tb',//默认的连线与节点接触的方式(border:边缘/ltrb:上下左右/tb:上下/lr:左右)当布局为树状布局时应使用tb或者lr,这样才会好看defaultNodeBorderWidth:0.2,//节点边框粗细defaultcolor:'rgba(0, 186, 189, 1)',//默认的线条颜色defaultNodeColor:'rgba(0, 206, 209, 1)',//默认的节点背景颜色defaultNodeWidth:'80',//节点宽度defaultNodeHeight:'80',//节点高度defaultFocusRootNode:false,//默认为根节点添加一个被选中的样式moveToCenterWhenResize:true,//当图谱的大小发生变化时,是否重新让图谱的内容看起来居中// 这里可以参考"Graph 图谱"中的参数进行设置},};},activated(){this.showSeeksGraph();},methods:{showNodeTips(nodeObject, $event){this.currentNode = nodeObject;const _base_position =this.$refs.myPage.getBoundingClientRect();this.isShowNodeTipsPanel =true;this.nodeMenuPanelPosition.x = $event.clientX - _base_position.x +10;this.nodeMenuPanelPosition.y = $event.clientY - _base_position.y +10;},hideNodeTips(nodeObject, $event){this.isShowNodeTipsPanel =false;},callback(val){this.activeKey = val;this.showSeeksGraph();},//渲染节点和连接线showSeeksGraph(){getRelationship().then((res)=>{let nodes = res.node_list ||[];let links = res.edge_list ||[];var __graph_json_data ={rootId:'0',nodes: nodes,links: links,};// 以上数据中的node和link可以参考"Node节点"和"Link关系"中的参数进行配置this.$refs.seeksRelationGraph.setJsonData(
__graph_json_data,(graphInstance)=>{// Called when the relation-graph is completedsetTimeout(()=>{
graphInstance.stopAutoLayout();},1000);});});},//点击节点触发的函数onNodeClick(nodeObject, $event){const allLinks =this.$refs.seeksRelationGraph.getLinks();
allLinks.forEach((link)=>{// 还原所有样式
link.relations.forEach((line)=>{if(line.data.orignColor){
line.color = line.data.orignColor;}if(line.data.orignFontColor){
line.fontColor = line.data.orignColor;}if(line.data.orignLineWidth){
line.lineWidth = line.data.orignLineWidth;}});});// 让与{nodeObject}相关的所有连线高亮
allLinks
.filter((link)=> link.fromNode === nodeObject || link.toNode === nodeObject
).forEach((link)=>{
link.relations.forEach((line)=>{
line.data.orignColor = line.color;
line.data.orignFontColor = line.fontColor || line.color;
line.data.orignLineWidth = line.lineWidth ||1;
line.color ='#ff0000';
line.fontColor ='#ff0000';
line.lineWidth =3;});});// 有时候更改一些属性后,并不能马上同步到视图,这需要以下方法让视图强制根据数据同步到最新this.$refs.seeksRelationGraph.getInstance().dataUpdated();},//店家连接线触发的函数onLineClick(lineObject, $event){
console.log('onLineClick:', lineObject);// this.$notify({// title: '点击连线:',// type: 'success',// message: '点击了线:' + linkObject.fromNode.text + ' to ' + linkObject.toNode.text// });},},};</script>
3.3 css部分代码
<style lang="less" scoped>
.c-my-node2{border: none;background-position: center center;background-size: 100%;height: 74px;width: 74px;border-radius: 40px;}.c-node-name2{width: 160px;margin-left: -40px;text-align: center;margin-top: 85px;position: absolute;}.c-node-menu-item{line-height: 30px;padding-left: 10px;cursor: pointer;color: #444444;font-size: 14px;border-top: #efefef solid 1px;}.c-node-menu-item:hover{background-color:rgba(66, 187, 66, 0.2);}
</style>
版权归原作者 叶浩成520 所有, 如有侵权,请联系我们删除。