使用relation-graph实现企业关系图谱

需求

需要显示企业的关系图谱。

1、安装relation-graph(http://relation-graph.com/)

npm install --save relation-graph

2、引入relation-graph:

import RelationGraph from 'relation-graph';

3、创建dom:

<template>
  <div>
    <div class="graph" ref="graph" style="height:calc(100vh - 50px);" @click="canvasClick">
      <RelationGraph ref="seeksRelationGraph" :options="graphOptions" :on-node-click="onNodeClick" :on-line-click="onLineClick">
        <div slot="node" class="node" slot-scope="{ node }" @mouseover="showNodeTips(node, $event)" @mouseout="hideNodeTips(node, $event)">
          <div v-if="node.data.labels.includes('Company')" class="company-node">
            {{ node.text }}
          </div>
          <div v-else class="human-node">{{ node.text }}</div>
        </div>
      </RelationGraph>
    </div>
    <div v-if="isShowNodeTipsPanel" :style="{ left: nodeMenuPanelPosition.x + 'px', top: nodeMenuPanelPosition.y + 'px' }" class="node-dialog">
      <div>{{ currentNode.text }}</div>
    </div>
  </div>
</template>

4、js配置(数据来源于企查查的小米关系图谱数据):

<script>
import RelationGraph from 'relation-graph';
import { xiaomi } from './xiaomi';
export default {
  name: 'RelationGraphIndex',
  components: { RelationGraph },
  data() {
    return {
      // 图谱配置
      graphOptions: {
        backgrounImage: require('@/assets/images/bg.webp'), // 水印
        backgrounImageNoRepeat: true, // 只在右下角显示水印,不重复显示水印
        allowShowMiniToolBar: true, // 是否显示工具栏
        allowShowMiniView: true, // 是否显示缩略图
        allowShowMiniNameFilter: false, // 是否显示搜索框
        allowSwitchLineShape: true, // 是否在工具栏中显示切换线条形状的按钮
        allowSwitchJunctionPoint: true, // 是否在工具栏中显示切换连接点位置的按钮
        disableZoom: false, // 是否禁用图谱的缩放功能,这里特指通过鼠标滚轮进行缩放的功能,禁用后你依然可以通过图谱工具栏按钮进行缩放
        disableDragNode: false, // 是否禁用图谱中节点的拖动
        moveToCenterWhenResize: true, // 当图谱的大小发生变化时,是否重新让图谱的内容看起来居中
        // defaultFocusRootNode: '', // 默认为根节点添加一个被选中的样式
        allowShowZoomMenu: true, // 是否在右侧菜单栏显示放大缩小的按钮
        isMoveByParentNode: true, // 是否在拖动节点后让子节点跟随
        hideNodeContentByZoom: true, // 是否根据缩放比例隐藏节点内容
        defaultNodeShape: 0, // 默认的节点形状,0:圆形;1:矩形
        // defaultNodeColor: '', // 默认的节点背景颜色
        // defaultNodeFontColor: '', // 默认的节点文字颜色
        // defaultNodeBorderWidth: '2px', // 默认的节点边框粗细(像素)
        // defaultNodeWidth: '40px', // 默认的节点宽度
        // defaultNodeHeight: '40px', // 默认的节点高度
        defaultJunctionPoint: 'border', // 默认的连线与节点接触的方式(border:边缘 / ltrb:上下左右 / tb:上下 / lr:左右)
        // defaultExpandHolderPosition: 'right', // 默认的节点展开/关闭按钮位置(left/top/right/bottom)
        // defaultLineColor: '', // 默认的线条颜色
        // defaultLineWidth: '', // 默认线条粗细(px)
        // defaultLineShape: '', // 默认的线条样式(1:直线/2:样式2/3:样式3/4:折线/5:样式5/6:样式6)
        // defaultLineMarker: '', // 默认的线条箭头样式
        // defaultShowLineLabel: '', // 默认是否显示连线文字
        // 布局方式
        layouts: [
          {
            layoutLabel: '自动布局', // 布局描述
            layoutName: 'force', // 布局方式(tree树状布局/center中心布局/force自动布局)
            layoutClassName: 'seeks-layout-force' // 当使用这个布局时,会将此样式添加到图谱上
          }
        ]
      },
      // 选中点
      currentNode: {},
      // 显示提示弹框
      isShowNodeTipsPanel: false,
      // 节点位置
      nodeMenuPanelPosition: { x: 0, y: 0 }
    };
  },
  mounted() {
    this.showSeeksGraph();
  },
  methods: {
    /**
     * 加载图谱
     * @date 2022-10-21
     * @returns {any}
     */
    showSeeksGraph() {
      let { nodes, relationships } = xiaomi;
      nodes = nodes.map((item) => {
        item.text = item.properties.name;
        item.data = { ...item };
        if (item.labels.includes('Company')) (item.borderColor = '#4ea2f0'), (item.color = '#4ea2f0'), (item.styleClass = 'company-node');
        if (item.labels.includes('Human')) (item.borderColor = '#ff6060'), (item.color = '#ff6060'), (item.width = 75), (item.height = 75);
        if (item.text === '小米科技有限责任公司') (item.borderColor = '#ffce7f'), (item.color = '#ff9e00');
        return item;
      });
      relationships = relationships.map((item) => {
        item.from = item.startNode;
        item.to = item.endNode;
        item.text = item.properties.role;
        return item;
      });
      let centerIds = nodes.find((item) => item.text === '小米科技有限责任公司');
      const obj = {
        rootId: centerIds.id,
        nodes,
        links: relationships
      };
      // 以上数据中的node和link可以参考"Node节点"和"Link关系"中的参数进行配置
      this.$refs.seeksRelationGraph.setJsonData(obj, (seeksRGGraph) => {
        // console.log(seeksRGGraph);
      });
    },
    /**
     * 节点点击
     * @date 2022-10-21
     * @param {any} nodeObject
     * @param {any} $event
     * @returns {any}
     */
    onNodeClick(nodeObject, $event) {
      console.log('节点数据:', nodeObject);
      const _all_nodes = this.$refs['seeksRelationGraph'].getNodes(),
        _all_lines = this.$refs['seeksRelationGraph'].getLines();
      const { lot } = nodeObject;
      // 子集高亮
      if (lot.childs && lot.childs.length) {
        _all_nodes.forEach((thisNode) => {
          let _isHideThisNode = false;
          lot.childs.forEach((childNode) => {
            if (thisNode.id === childNode.id || thisNode.id === nodeObject.id) {
              _isHideThisNode = true;
            }
            if (lot.parent && thisNode.id === lot.parent.id) {
              _isHideThisNode = true;
            }
          });
          thisNode.opacity = _isHideThisNode ? 1 : 0.1;
        });
      } else {
        // 父级及本身高亮
        _all_nodes.forEach((thisNode) => {
          let _isHideThisNode = false;
          if (thisNode.id === nodeObject.id) {
            _isHideThisNode = true;
          }
          if (lot.parent && thisNode.id === lot.parent.id) {
            _isHideThisNode = true;
          }
          thisNode.opacity = _isHideThisNode ? 1 : 0.1;
        });
      }
    },
    /**
     * 线条点击
     * @date 2022-10-21
     * @param {any} lineObject
     * @param {any} $event
     * @returns {any}
     */
    onLineClick(lineObject, $event) {
      console.log('线条数据:', lineObject);
    },
    /**
     * 鼠标移入显示提示
     * @date 2022-10-21
     * @param {any} nodeObject
     * @param {any} $event
     * @returns {any}
     */
    showNodeTips(nodeObject, $event) {
      this.currentNode = nodeObject;
      const _base_position = this.$refs.graph.getBoundingClientRect();
      this.isShowNodeTipsPanel = true;
      this.nodeMenuPanelPosition.x = $event.clientX - _base_position.x + 90;
      this.nodeMenuPanelPosition.y = $event.clientY - _base_position.y - 20;
    },
    /**
     * 鼠标移出隐藏提示
     * @date 2022-10-21
     * @param {any} nodeObject
     * @param {any} $event
     * @returns {any}
     */
    hideNodeTips(nodeObject, $event) {
      this.isShowNodeTipsPanel = false;
    },
    /**
     * 点击图谱
     * @date 2022-10-21
     * @returns {any}
     */
    canvasClick() {
      const _all_nodes = this.$refs['seeksRelationGraph'].getNodes();
      _all_nodes.forEach((thisNode) => {
        let _isHideThisNode = true;
        thisNode.opacity = _isHideThisNode ? 1 : 0.1;
      });
    }
  }
};
</script>

5、scss样式

<style lang="scss" scoped>
.graph {
  position: relative;
}
.node {
  height: 100%;
}
.company-node {
  width: 100%;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  line-height: 17px;
  cursor: pointer;
}
.human-node {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.node-dialog {
  z-index: 9999;
  padding: 10px;
  background-color: #ffffff;
  border: #eeeeee solid 1px;
  box-shadow: 0px 0px 8px #cccccc;
  position: absolute;
}
</style>

6、最终效果:

在这里插入图片描述
在这里插入图片描述

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值