最近需求需要做一个表格节点的组织树,试了很多 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数据渲染图表及导出图片(页面显示正常导出图片最右侧节点被截断无法完整导出)
使用dataB数据渲染图表及导出图片(页面显示正常导出图片正常)
后来发现 叶子节点为偶数时导出图片最右侧节点都会显示不完整,不清楚是为什么
目前解决办法只能在偶数叶子节点的时候手动加一个虚拟节点并且不显示,让导出图片没有问题
有没有大佬知道是为啥啊,该怎么解决呢