vue2引用antvG6渲染树结构

首先安装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官网 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值