首先安装antvG6
npm install @antv/g6 --save
然后再所需的.vue文件引入,或者写入公告组件
<template>
<div class="app_box">
<div ref="graphContainer"></div>
</div>
</template>
<script>
import { TreeGraph } from "@antv/g6";
import G6 from "@antv/g6";
export default {
name: "TreeGraphComponent",
data() {
return {
maxDepthFromSecondLevel: null, //树结构容器的高度
graph: null,
dataJSon: {
value: "落实网络和电子设备安全(D9)",
children: [
{
children: [
{
value: "落实网络和电子设备安全落实网络和电子设备安全",
children: [
{
value: "落实网络和电子设备安全",
children: [{}],
},
],
},
],
value: "落实网络和电子设备安全",
},
{
children: [
{
value: "落实网络和电子设备安全",
children: [
{
value: "落实网络和电子设备安全",
children: [{}],
},
],
},
],
value: "落实网络和电子设备安全落实网络和电子设备安全",
},
{
children: [
{
value:
"落实网络和电子设备安全落实网络和电子设备安全落实网络和电子设备安全",
children: [
{
value: "落实网络和电子设备安全",
children: [],
},
],
},
],
value: "落实网络和电子设备安全",
},
{
children: [
{
value: "落实网络和电子设备安全",
children: [
{
value: "落实网络和电子设备安全",
children: [],
},
],
},
],
value: "落实网络和电子设备安全",
},
],
},
COLLAPSE_ICON: function COLLAPSE_ICON(x, y, r) {
return [
// ["M", x, y],
// ["a", r, r, 0, 1, 0, r * 2, 0],
// ["a", r, r, 0, 1, 0, -r * 2, 0],
// ["M", x + 2, y],
// ["L", x + 2 * r - 2, y],
];
},
EXPAND_ICON: function EXPAND_ICON(x, y, r) {
return [
["M", x, y],
["a", r, r, 0, 1, 0, r * 2, 0],
["a", r, r, 0, 1, 0, -r * 2, 0],
["M", x + 2, y],
["L", x + 2 * r - 2, y],
["M", x + r, y - r + 2],
["L", x + r, y + r - 2],
];
},
};
},
mounted() {
window.removeEventListener("resize", this.onResize);
// 设置动态高度,根据children的层级去设置高度,默认高度200
this.maxDepthFromSecondLevel =
this.getMaxRemainingLevelsFromSecondLevel(this.dataJSon) * 50 + 200;
// 如遇到后端返回的数据children含有[{}],可用此方法转为[],否则页面会渲染数据最后一级为null
this.cleanEmptyChildren(this.dataJSon);
this.initGraph(this.dataJSon);
},
methods: {
cleanEmptyChildren(obj) {
if (Array.isArray(obj.children)) {
obj.children = obj.children.map((child) => {
this.cleanEmptyChildren(child);
if (
Array.isArray(child.children) &&
child.children.length === 1 &&
Object.keys(child.children[0]).length === 0
) {
return { ...child, children: [] };
}
return child;
});
if (obj.children.length === 0) {
obj.children = [];
}
}
},
getMaxRemainingLevelsFromSecondLevel(node) {
if (!node || !node.children || node.children.length === 0) {
return 0;
}
let maxDepth = 0;
for (let secondLevelNode of node.children) {
const depth = this.countRemainingLevels(secondLevelNode);
if (depth > maxDepth) {
maxDepth = depth;
}
}
return maxDepth;
},
countRemainingLevels(node) {
if (!node || !node.children || node.children.length === 0) {
// 如果没有子节点,或者当前节点不是对象,返回0
return 0;
}
let maxDepth = 0;
for (let child of node.children) {
// 递归计算每个子节点的深度,并取最大值
const depth = 1 + this.countRemainingLevels(child); // 1代表当前这一层
if (depth > maxDepth) {
maxDepth = depth;
}
}
return maxDepth;
},
initGraph(dataJSon) {
G6.registerNode(
"tree-node",
{
drawShape: (cfg, group) => {
let rect = group.addShape("rect", {
attrs: {
fill: "#fff",
stroke: "#666",
},
});
let result = "";
let currentLength = 0;
for (let i = 0; i < cfg.value.length; i++) {
// 设置value的length超过6的时候就加换行符使其换行,避免数据量太多导致重叠
if (currentLength >= 6) {
result += "\n";
currentLength = 0;
}
result += cfg.value[i];
currentLength++;
}
let content = result;
let text = group.addShape("text", {
attrs: {
text: content,
x: 0,
y: 0,
textAlign: "center",
textBaseline: "middle",
fill: "#666",
fontSize: 16, // 设置的字体大小,可根据业务需求去调试
},
dropCap: false,
});
let bbox = text.getBBox();
let hasChildren = cfg.children && cfg.children.length > 0;
if (hasChildren) {
group.addShape("marker", {
attrs: {
x: bbox.maxX + 6,
y: bbox.minX + bbox.height / 2 - 6,
r: 6,
symbol: this.COLLAPSE_ICON,
stroke: "#666",
lineWidth: 2,
},
className: "collapse-icon",
});
}
rect.attr({
x: bbox.minX - 4,
y: bbox.minY - 6,
width: bbox.width + (hasChildren ? 26 : 8),
height: bbox.height + 12,
});
return rect;
},
},
"single-shape"
);
this.graph = new TreeGraph({
container: this.$refs.graphContainer,
width: window.innerWidth, //默认宽度,可以根据业务需求调整
fitViewPadding: [20, 20, 20, 20],
height: this.maxDepthFromSecondLevel,
minZoom: 0.3, //最小比例
maxZoom: 1, //最大比例
modes: {
default: [
// 'drag-canvas',
// 'zoom-canvas',
"drag-node", // 仅允许拖动节点
],
},
defaultNode: {
type: "tree-node",
style: {
stroke: "#A3B1BF",
},
},
defaultEdge: {
type: "cubic-horizontal",
style: {
stroke: "#A3B1BF",
},
},
layout: {
type: "compactBox",
direction: "TB",
getId: (d) => d.id,
getHeight: () => 20,
getWidth: () => 20,
getVGap: () => 40,
getHGap: () => 150,
},
});
G6.Util.traverseTree(dataJSon, (item) => {
item.id = item.id;
});
this.graph.data(dataJSon);
this.graph.render();
this.graph.fitView();
},
},
onResize() {
graph.fitView();
},
};
</script>
<style scoped>
.app_box {
height: 100%;
}
</style>
本篇只是简单了解antvG6的一些属性以及如何去渲染树结构,如需了解更多,请访问antv官网