股权结构树状图(多父级,多对一,自定义坐标)

介绍

        基于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);
    },

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值