relation-graph组织结构图 导出图片显示不全

487 阅读7分钟

最近需求需要做一个表格节点的组织树,试了很多 relation-graph最满足需求,但是遇到一个问题,有一种情况导出的图片节点无法完整显示

代码如下:

index.vue

<template>
  <div :style="`height: 700px`">
    <RelationGraph
      ref="relationRef"
      :options="graphOptions"
      :on-node-click="onNodeClick"
      :on-line-click="onLineClick"
    >
      <template #node="{node}">
        <NodeTem :nodeData="node.data" />
      </template>
    </RelationGraph>
  </div>
</template>
<script>
import RelationGraph from 'relation-graph'
import NodeTem from './nodeTem.vue'
import { dataA } from './data'
export default {
  components: {
    RelationGraph,
    NodeTem,
    // RGMiniView
  },
  data() {
    return {
      title: '导出图片名称',
      graphOptions: {
        backgrounImageNoRepeat: true,
        // defaultNodeShape: 0,
        moveToCenterWhenRefresh: true,
        zoomToFitWhenRefresh: false,
        defaultExpandHolderPosition: 'bottom',
        placeOtherGroup: false,
        debug: false,
        // graphOffset_x: 0,
        // graphOffset_y: 0,
        defaultJunctionPoint: 'tb',
        defaultLineShape: 4,
        disableDragNode: true, // 禁止拖动节点
        disableNodeClickEffect: true,
        disableLineClickEffect: true,
        defaultNodeWidth: 502,
        layout: {
          label: '中心',
          layoutName: 'tree',
          // centerOffset_x: 0,
          // centerOffset_y: 0,
          // distance_coefficient: 1,
          from: 'top',
          layoutClassName: 'seeks-layout-center',
          layoutDirection: 'v'
        }
      },
      currentLeaveNodeIndex: -1,
      rgInstanceRef: null
    }
  },
  methods: {
    onNodeClick() {},
    onLineClick() {},
    // 树结构布局  为防止子节点重叠 计算每个子节点的x、y并赋值
    // 按照数据的总叶子节点个数来计算总宽度
    // 每个节点包含的叶子节点的leaveNodeIndex及包含的叶子节点个数leaveNodeLength
    // 每个节点的y坐标为父节点的y坐标+父节点的高度height+100(每层节点间距假设为100)
    // 每个节点的x坐标为当前节点的 leaveNodeIndex * 510 + (leaveNodeLength - 1) * 255(假设节点宽度为500  每列节点间距为10   当前公式为推算化简得出)
    recursionTree(list, parentInfo = { y: 0, height: 0, id: '' }) {
      let nodeList = []
      let linkList = []
      console.log('list', list)
      list.forEach(async (item, index) => {
        return new Promise((resolve) => {
          item.height = 35 * (item.list.length + 1)
          item.y = parentInfo.y + parentInfo.height + 100
  
          // 先遍历数据 确认每个节点包含的首个叶子节点的下标及叶子几点的数量(i, l)
          if (item.children && item.children.length > 0) {
            const childrenList = this.recursionTree(item.children, item)
            item.leaveNodeIndex = item.children[0].leaveNodeIndex
            item.leaveNodeLength = item.children.reduce((total, cur) => total + cur.leaveNodeLength, 0)
  
            nodeList = nodeList.concat(childrenList.nodeList)
            linkList = linkList.concat(childrenList.linkList)
  
          } else {
            this.currentLeaveNodeIndex += 1
            item.leaveNodeIndex = this.currentLeaveNodeIndex
            item.leaveNodeLength = 1
          }
          const x = item.leaveNodeIndex * 510 + (item.leaveNodeLength - 1) * 255
  
          item.x = x
  
          nodeList.push({
            id: item.id, // node节点的id需要唯一
            x: item.x,
            y: item.y,
            fixed: true,
            data: item,
            text: item.text,
            width: 500
            // expandHolderPosition: item.children && item.children.length > 0 ? 'bottom' : 'hide'
          })
          if (parentInfo.id) {
            linkList.push({ from: parentInfo.id, to: item.id })
          }
          resolve()
        })
      })
      return { nodeList, linkList }
    },
    refreshGraph(downloadImage = false) {
      return new Promise((resolve, reject) => {
        this.currentLeaveNodeIndex = -1
        const { nodeList, linkList } = this.recursionTree(dataA)
        // // 共有偶数个叶子节点的情况 偶数个叶子节点导出图片时最右侧节点会显示不完整
        // if (this.currentLeaveNodeIndex % 2 === 1) {
        //   // 防止导出图片显示不完整 手动添加一个虚拟节点
        //   const maxX = Math.max(...nodeList.map(item => item.x))
        //   nodeList.push({ id: 'custom', text: 'custom', width: 500, x: maxX + 100, y: 0, opacity: 0, fixed: true, data: { list: [] } })
        // }
        const json_data = {
          nodes: nodeList,
          links: linkList,
          rootId: 'A'
        };
        this.rgInstanceRef.setJsonData(json_data, (graphInstance) => {
          // 这些写上当图谱初始化完成后需要执行的代码.
          if (downloadImage) {
            graphInstance.downloadAsImage('png', this.title).then(() => {
              resolve()
            })
          } else {
            resolve()
          }
        });
      })
    },
    saveImg() {
      return new Promise(resolve => {
        this.rgInstanceRef.getInstance().downloadAsImage('png', this.title).then(() => {
          resolve()
        })
      })
    }
  },
  mounted() {
    this.rgInstanceRef = this.$refs.relationRef
    this.refreshGraph()
  }
}
</script>

nodeTem.vue

<template>
  <div style="background-color: #ffffff;">
    <a-table
      :dataSource="nodeData.list"
      :columns="columns"
      bordered
      size="small"
      :pagination="false"
      style="width: 500px;background:#fff;"
      :rowKey="(row, index) => index"
    >
    </a-table>
  </div>
</template>
<script>
export default {
  props: {
    nodeData: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      columns: [
        {
          title: '字段1',
          dataIndex: 'field1'
        },
        {
          title: '字段2',
          dataIndex: 'field2'
        },
        {
          title: '字段3',
          dataIndex: 'field3'
        },
        {
          title: '字段4',
          dataIndex: 'field4'
        },
        {
          title: '字段5',
          dataIndex: 'field5'
        }
      ],
    }
  }
}
</script>

data.js

export const dataA = [  {    id: 'A',    text: 'A',    list: [      { field1: 'a11', field2: 'a21', field3: 'a31', field4: 'a41', field5: 'a51' },    ],
    children: [
      {
        id: 'B',
        text: 'B',
        list: [
          { field1: 'b11', field2: 'b21', field3: 'b31', field4: 'b41', field5: 'b51' },
          { field1: 'b12', field2: 'b22', field3: 'b32', field4: 'b42', field5: 'b52' },
          { field1: 'b13', field2: 'b23', field3: 'b33', field4: 'b43', field5: 'b53' },
          { field1: 'b14', field2: 'b24', field3: 'b34', field4: 'b44', field5: 'b54' },
        ]
      },
      {
        id: 'C',
        text: 'C',
        list: [
          { field1: 'c11', field2: 'c21', field3: 'c31', field4: 'c41', field5: 'c51' },
          { field1: 'c12', field2: 'c22', field3: 'c32', field4: 'c42', field5: 'c52' },
          { field1: 'c13', field2: 'c23', field3: 'c33', field4: 'c43', field5: 'c53' },
        ],
        children: [
          {
            id: 'D',
            text: 'D',
            list: [
              { field1: 'd11', field2: 'd21', field3: 'd31', field4: 'd41', field5: 'd51' },
              { field1: 'd12', field2: 'd22', field3: 'd32', field4: 'd42', field5: 'd52' },
            ],
          },
          {
            id: 'E',
            text: 'E',
            list: [
              { field1: 'e11', field2: 'e21', field3: 'e31', field4: 'e41', field5: 'e51' },
              { field1: 'e12', field2: 'e22', field3: 'e32', field4: 'e42', field5: 'e52' },
              { field1: 'e13', field2: 'e23', field3: 'e33', field4: 'e43', field5: 'e53' },
              { field1: 'e14', field2: 'e24', field3: 'e34', field4: 'e44', field5: 'e54' },
            ],
          },
          {
            id: 'F',
            text: 'F',
            list: [
              { field1: 'f11', field2: 'f21', field3: 'f31', field4: 'f41', field5: 'f51' },
              { field1: 'f12', field2: 'f22', field3: 'f32', field4: 'f42', field5: 'f52' },
              { field1: 'f13', field2: 'f23', field3: 'f33', field4: 'f43', field5: 'f53' },
              { field1: 'f14', field2: 'f24', field3: 'f34', field4: 'f44', field5: 'f54' },
              { field1: 'f15', field2: 'f25', field3: 'f35', field5: 'f45', field5: 'f55' },
              { field1: 'f16', field2: 'f26', field3: 'f36', field6: 'f46', field5: 'f56' },
            ],
          }
        ]
      }
    ]
  }
]
export const dataB = [  {    id: 'A',    text: 'A',    list: [      { field1: 'a11', field2: 'a21', field3: 'a31', field4: 'a41', field5: 'a51' },    ],
    children: [
      {
        id: 'B',
        text: 'B',
        list: [
          { field1: 'b11', field2: 'b21', field3: 'b31', field4: 'b41', field5: 'b51' },
          { field1: 'b12', field2: 'b22', field3: 'b32', field4: 'b42', field5: 'b52' },
          { field1: 'b13', field2: 'b23', field3: 'b33', field4: 'b43', field5: 'b53' },
          { field1: 'b14', field2: 'b24', field3: 'b34', field4: 'b44', field5: 'b54' },
        ]
      },
      {
        id: 'C',
        text: 'C',
        list: [
          { field1: 'c11', field2: 'c21', field3: 'c31', field4: 'c41', field5: 'c51' },
          { field1: 'c12', field2: 'c22', field3: 'c32', field4: 'c42', field5: 'c52' },
          { field1: 'c13', field2: 'c23', field3: 'c33', field4: 'c43', field5: 'c53' },
        ],
        children: [
          {
            id: 'D',
            text: 'D',
            list: [
              { field1: 'd11', field2: 'd21', field3: 'd31', field4: 'd41', field5: 'd51' },
              { field1: 'd12', field2: 'd22', field3: 'd32', field4: 'd42', field5: 'd52' },
            ],
          },
          {
            id: 'E',
            text: 'E',
            list: [
              { field1: 'e11', field2: 'e21', field3: 'e31', field4: 'e41', field5: 'e51' },
              { field1: 'e12', field2: 'e22', field3: 'e32', field4: 'e42', field5: 'e52' },
              { field1: 'e13', field2: 'e23', field3: 'e33', field4: 'e43', field5: 'e53' },
              { field1: 'e14', field2: 'e24', field3: 'e34', field4: 'e44', field5: 'e54' },
            ],
          },
          {
            id: 'F',
            text: 'F',
            list: [
              { field1: 'f11', field2: 'f21', field3: 'f31', field4: 'f41', field5: 'f51' },
              { field1: 'f12', field2: 'f22', field3: 'f32', field4: 'f42', field5: 'f52' },
              { field1: 'f13', field2: 'f23', field3: 'f33', field4: 'f43', field5: 'f53' },
              { field1: 'f14', field2: 'f24', field3: 'f34', field4: 'f44', field5: 'f54' },
              { field1: 'f15', field2: 'f25', field3: 'f35', field5: 'f45', field5: 'f55' },
              { field1: 'f16', field2: 'f26', field3: 'f36', field6: 'f46', field5: 'f56' },
            ],
          },
          {
            id: 'G',
            text: 'G',
            list: [
              { field1: 'g11', field2: 'g21', field3: 'g31', field4: 'g41', field5: 'g51' },
              { field1: 'g12', field2: 'g22', field3: 'g32', field4: 'g42', field5: 'g52' },
              { field1: 'g13', field2: 'g23', field3: 'g33', field4: 'g43', field5: 'g53' },
              { field1: 'g14', field2: 'g24', field3: 'g34', field4: 'g44', field5: 'g54' },
              { field1: 'g15', field2: 'g25', field3: 'g35', field5: 'g45', field5: 'g55' },
              { field1: 'g16', field2: 'g26', field3: 'g36', field6: 'g46', field5: 'g56' },
            ],
          }
        ]
      }
    ]
  }
]

使用dataA数据渲染图表及导出图片(页面显示正常导出图片最右侧节点被截断无法完整导出)

image.png

relation-graph-71042.png

使用dataB数据渲染图表及导出图片(页面显示正常导出图片正常)

image.png

relation-graph-84104.png

后来发现 叶子节点为偶数时导出图片最右侧节点都会显示不完整,不清楚是为什么

目前解决办法只能在偶数叶子节点的时候手动加一个虚拟节点并且不显示,让导出图片没有问题

有没有大佬知道是为啥啊,该怎么解决呢