G6 draws a tree diagram (custom node, custom edge, custom layout)

1 Design Node

Define all nodes in registerNode

G6.registerNode('tree-node', {
    
    
	drawShape: function drawShape(cfg, group) {
    
    
	定义图中需要的节点
	}
}, 'single-node',);

In order to use the built-in layout method, select the parameter as 'tree-node' tree node type, the data format can have children sub-nodes, and the effect will automatically generate a sub-tree cfg can
get the data, such as cfg.id, cfg.name

1.1 Define nodes and text

Use group.addShape('rect', {}) to define node rect
configuration parameters: https://antv-g6.gitee.io/zh/docs/api/shapeProperties/#fill

        // 定义节点 rect 
        const rect = group.addShape('rect', {
    
      // 'rect'表示矩形图形
          attrs: {
    
    
            // 节点定义参数:颜色、阴影...
          },
          name: 'rect-shape',   // 为这个节点起名字 不过没有使用过这个名字
        });

Use group.addShape('text', {}) to define the text text

		// 定义文本text
        const text = group.addShape('text', {
    
      // 'text'表示文本
          attrs: {
    
    
            // 参数:颜色、文字...
          },
          name: 'text-shape',
        });

After the nodes and text are generated, define their relative positions.
Refer to the official website to define complex graph styles: https://antv-g6.gitee.io/zh/examples/tree/customItemTree#customTree
Use .getBBox() to get the text The box bbox, using the position coordinates behind the relative position of the text box

        const bbox = text.getBBox();   // 获得文本的盒子
        // 设置rect 节点的位置
        rect.attr({
    
    
          x: -bbox.width / 2 - 5,   // x坐标
          y: -bbox.height,			// y坐标
          width: bbox.width +  12 ,	 // 宽
          height: bbox.height + 8,   // 高
        });
        // 设置text文本的位置
        text.attr({
    
    
          x: -bbox.width / 2,
          y: -bbox.height / 2 + 3,
        })

The effect is as follows
insert image description here

1.2 Adding nodes

If you want to add another small node to the node, and the position moves with the large node, as shown in the figure,
insert image description here
add a new node and text rect2 text2

rect2 = group.addShape('rect', {
    
    
        attrs: {
    
    
                // 参数
        },
        name: 'rect-shape2',
});
const text2 = group.addShape('text', {
    
    
        attrs: {
    
    
                // 参数
        },
        name: 'text-shape2',
});

Set coordinates for rect2 text2, take bbox as reference position

              // 设置坐标轴和宽高
              rect2.attr({
    
    
                  x: -bbox.width / 2 - 24,
                  y: -bbox.height / 2 - 1,
                  width: 14,
                  height: 10,
              });
              text2.attr({
    
    
                  x: -bbox.width / 2 - 23,
                  y: -bbox.height / 2 + 4,
              })

1.3 Custom node style

			roup.addShape('dom', {
    
    
                attrs: {
    
    
                  x: -bbox.width / 2 - 24 + 14,   // 即:rect的坐标 + rect的宽 
                  y: -bbox.height / 2 - 1,
                  width: 10,
                  height: 10,
                  html: `
                  <div style="border: 5px solid red;">
                  	自定义dom
                  </div>
                    `,
                },
                draggable: true,
              });

Use custom dom, need to set in new G6.TreeGraph

renderer : 'svg',   // 奇怪的是设置之后原来节点的布局有些影响

2 Treemap configuration

2.1 Allow the use of custom dom nodes

renderer : 'svg', 

2.2 Built-in behavior

https://antv-g6.gitee.io/zh/docs/manual/middle/states/defaultBehavior#%E5%86%85%E7%BD%AE-behavior

modes: {
    
    
          default: [
            {
    
    
              type: 'collapse-expand',
              onChange: function onChange(item, collapsed) {
    
    
                const data = item.get('model');
                graph.updateItem(item, {
    
    
                  collapsed,
                });
                data.collapsed = collapsed;
                return true;
              },
            },
            'drag-canvas',    // 允许拖动
            'zoom-canvas',	 // ....
          ],
        },

custom side

defaultEdge: {
    
    
          type: 'cubic-horizontal',
          style: {
    
    
            stroke: 'red'   //红色
          },
        },

layout layout

https://antv-g6.gitee.io/zh/docs/manual/middle/layout/tree-graph-layout

layout: {
    
    
            type: 'indented',
            direction: 'LR',   // 节点从左向右分布
            dropCap: false,
            indent: 190,
            getHeight: () => {
    
    
              return 13;
            },
            getVGap: function getVGap () {
    
    
              return 10;
            },
        },

demo

<template>
    <div class="main-content-box">
      <div id="container"></div>
    </div>
</template>
  
  <script>
  import G6 from '@antv/g6';

  export default {
    
    
    name: 'multTagsSec',
    data () {
    
    
      return {
    
    
        gDatas:{
    
    
                "id": "1",
                "name": "storehouse A",
                "children": [
                  {
    
    
                    "id": "2",
                    "name": "B",
                    "percentage": "60%",
                    "children": [
                      {
    
    
                        "id": "3",
                        "name": "storehouse C",
                        "percentage": "80%",
                        "children": [
                          {
    
    
                            "name": "storehouse C",
                            "percentage": "80%",
                            "children": [
                              {
    
    
                                "name": "D",
                                "percentage": "20%"
                              },
                              {
    
    
                                "name": "storehouselllllll C",
                                "percentage": "20%"
                              }
                            ]
                          },
                          {
    
    
                            "name": "storehouse D",
                            "percentage": "20%"
                          }
                        ]
                      },
                      {
    
    
                        "name": "storehouse D",
                        "percentage": "20%"
                      }
                    ]
                  },
                  {
    
    
                    "name": "storehouse C",
                    "percentage": "100%"
                  },
                  {
    
    
                    "name": "storehouse B",
                    "percentage": "20%"
                  },
                  {
    
    
                    "name": "storehouse C",
                    "percentage": "20%"
                  },
                  {
    
    
                    "name": "storehouse C",
                    "percentage": "20%",
                    "children": [
                              {
    
    
                                "name": "D",
                                "percentage": "20%"
                              },
                              {
    
    
                                "name": "storehouse A",
                                "percentage": "20%"
                                
                              }
                            ]
                  }
                ]
              }
  
      }
    },
    mounted() {
    
    
      this.getInit();
    },
    methods: {
    
    
      getInit () {
    
    
        // var mycfg = null;
        G6.registerNode('tree-node', {
    
    
          drawShape: function drawShape(cfg, group) {
    
    
            // console.log(cfg)
            
            // --------------------标签内容节点----------------------
            var hasChildren = cfg.children && cfg.children.length > 0;   // 是否有孩子节点
            var strokeColor =  hasChildren == true ? 'red' : null     // 有孩子 为红色
            // 节点设置 
            const rect = group.addShape('rect', {
    
    
              attrs: {
    
    
                fill: '#fff',
                stroke: strokeColor,  // 边框颜色
                lineWidth: 1,       // 边框粗细
                radius: 2,
                shadowBlur: 15,
                shadowColor: '#666',
                // shadowOffsetX: 2,
                // shadowOffsetY: 2
              },
              name: 'rect-shape',
            });
            // 文本设置
            const text = group.addShape('text', {
    
    
              attrs: {
    
    
                text: cfg.name,       // 赋值name属性
                fontFamily: 'normal',
                fontSize: 11,
                fontWeight: 800,
                x: 0,
                y: 0,
                textAlign: 'left',
                textBaseline: 'middle',
                fill: '#666'
              },
              name: 'text-shape',
            });
            
            const bbox = text.getBBox();   // 获得文本的盒子 之后的两个节点的xy轴坐标参考bbox
            //const minbbox = rect.getBBox();
            // 设置 rect方框和text文本 的 x y坐标轴
            rect.attr({
    
    
              x: -bbox.width / 2 - 5,
              y: -bbox.height,
              // width: bbox.width + (hasChildren ? 20 : 12),
              width: bbox.width +  12 ,
              height: bbox.height + 8,
            });
            text.attr({
    
    
              x: -bbox.width / 2,
              y: -bbox.height / 2 + 3,
            })
            
            // -----------百分比节点----------
            var hasPercentage = cfg.percentage;
            var rect2 = 0;
            if(hasPercentage){
    
    
                // 节点设置 2
                rect2 = group.addShape('rect', {
    
    
                attrs: {
    
    
                    fill: '#4682B4',
                    stroke: '',  // 边框颜色
                    lineWidth: 0,       // 边框粗细
                    shadowBlur: 0,
                    shadowColor: '',
                },
                name: 'rect-shape2',
              });
              // 文本设置 2
              const text2 = group.addShape('text', {
    
    
              attrs: {
    
    
                  text: cfg.percentage,       // 赋值name属性
                  fontFamily: 'normal',
                  fontSize: 5,
                  fontWeight: 500,
                  textAlign: 'left',
                  textBaseline: 'middle',
                  fill: 'white'
                },
                name: 'text-shape2',
              });
              // 设置坐标轴和宽高
              rect2.attr({
    
    
                  x: -bbox.width / 2 - 24,
                  y: -bbox.height / 2 - 1,
                  width: 14,
                  height: 10,
              });
              text2.attr({
    
    
                  x: -bbox.width / 2 - 23,
                  y: -bbox.height / 2 + 4,
              })
              // -------连接两个节点的小节点----------
              // const rect3 = group.addShape('rect', {
    
    
              //     attrs: {
    
    
              //         fill: '#00BFFF',
              //         stroke: '',  // 边框颜色
              //         lineWidth: 0,       // 边框粗细
              //         shadowBlur: 0,
              //         shadowColor: '',
              //     },
              //     name: 'rect-shape3',
              // });
              // rect3.attr({
    
    
              //     x: -bbox.width / 2 - 24 + 14,   // 即:rect的坐标 + rect的宽 
              //     y: -bbox.height / 4 + 1,
              //     width: 4,
              //     height: 4
              // });
              // -------连接两个节点的小节点 三角形----------
              // 需要设置svg才能使用
              group.addShape('dom', {
    
    
                attrs: {
    
    
                  x: -bbox.width / 2 - 24 + 14,   // 即:rect的坐标 + rect的宽 
                  y: -bbox.height / 2 - 1,
                  width: 10,
                  height: 10,
                  html: `
                  <div style="border-left: 5px solid red; 
                              border-right: 5px solid transparent;
                              border-top: 5px solid transparent;
                              border-bottom: 5px solid transparent;">
                  </div>
                    `,
                },
                draggable: true,
              });
            }
            

            // 小圆圈
            if (hasChildren) {
    
    
              const redcircle = group.addShape('marker', {
    
    
                  attrs: {
    
    
                  symbol: cfg.collapsed ? G6.Marker.expand : G6.Marker.collapse,
                  // symbol: cfg.collapsed ? COLLAPSE_ICON : EXPAND_ICON,
                  stroke: 'red',
                  fill: 'red',
                  lineWidth: 1.8,
                },
                name: 'collapse-icon',
              });
              redcircle.attr({
    
    
                  x: bbox.width / 2 + 7,
                  y: -3 ,
                  r: 4,

              })
            }

          

            return rect;
          },
          update: (cfg, item) => {
    
    
            const group = item.getContainer();
            const icon = group.find((e) => e.get('name') === 'collapse-icon');
            icon.attr('symbol', cfg.collapsed ? G6.Marker.expand : G6.Marker.collapse);
          },
        },
        'single-node',
      );
  
      const container = document.getElementById('container');
      const width = container.scrollWidth;
      const height = container.scrollHeight || 500;
  
      const graph = new G6.TreeGraph({
    
    
        renderer : 'svg',     // 创建自定义DMO时定义 会报一个错 但好像不影响 
        container: 'container',
        width,
        height,
        modes: {
    
    
          default: [
            {
    
    
              type: 'collapse-expand',
              onChange: function onChange(item, collapsed) {
    
    
                const data = item.get('model');
                graph.updateItem(item, {
    
    
                  collapsed,
                });
                data.collapsed = collapsed;
                return true;
              },
            },
            // 'drag-canvas',    // 不可拖动
            'zoom-canvas',
          ],
        },
        defaultNode: {
    
    
          type: 'tree-node',
          anchorPoints: [
            [0, 0.5],
            [1, 0.5],
          ],
        },
        // 设置边的参数
        defaultEdge: {
    
    
          type: 'cubic-horizontal',
          style: {
    
    
            stroke: 'red'
          },
        },
        layout: {
    
    
            type: 'indented',
            direction: 'LR',
            dropCap: false,
            indent: 190,
            getHeight: () => {
    
    
              return 13;
            },
            getVGap: function getVGap () {
    
    
              return 10;
            },
        },
      });
  
  
      
  
      graph.data(this.gDatas);
      graph.render();
      graph.fitView();
  
      if (typeof window !== 'undefined')
        window.onresize = () => {
    
    
          if (!graph || graph.get('destroyed')) return;
          if (!container || !container.scrollWidth || !container.scrollHeight) return;
          graph.changeSize(container.scrollWidth, container.scrollHeight);
        };
      },
  
  
  
  
    }
  }
  
  </script>
  
  <style scoped>
  </style>

insert image description here

Guess you like

Origin blog.csdn.net/weixin_52268321/article/details/129324972