G6绘制树形图(自定义节点、自定义边、自定义布局)

news2024/11/15 9:42:12

目录

  • 1 设计节点
    • 1.1 定义节点和文本
    • 1.2 增加节点
    • 1.3 自定义节点样式
  • 2 树图配置
    • 2.1 允许使用自定义dom节点
    • 2.2 内置行为
    • 自定义边
    • layout布局
  • demo

1 设计节点

在 registerNode 中定义所有的节点

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

为了使用内置的布局方式,选择参数为 ‘tree-node’ 树节点类型,数据格式可以存在children子节点,效果自动生成子树
cfg 可以拿到数据,如cfg.id、cfg.name

1.1 定义节点和文本

使用 group.addShape(‘rect’, {}) 定义节点 rect
配置参数:https://antv-g6.gitee.io/zh/docs/api/shapeProperties/#fill

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

使用 group.addShape(‘text’, {}) 定义文本 text

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

节点和文字生成后,再定义他们的相对位置
参考官网定义复杂图样式的方式:https://antv-g6.gitee.io/zh/examples/tree/customItemTree#customTree
使用 .getBBox() 获得该文本的盒子bbox,使用文本盒子的相对位置后面的位置坐标

        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,
        })

效果如下
在这里插入图片描述

1.2 增加节点

如果想为节点再增加一个小节点,并且位置随着大节点移动,如图
在这里插入图片描述
新增节点和文本 rect2 text2

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

为rect2 text2设置坐标,以bbox作为参考位置

              // 设置坐标轴和宽高
              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 自定义节点样式

			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,
              });

使用自定义dom,在 new G6.TreeGraph中 需要设置

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

2 树图配置

2.1 允许使用自定义dom节点

renderer : 'svg', 

2.2 内置行为

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',	 // ....
          ],
        },

自定义边

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

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>

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/393179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

aws appconfig 理解和使用appconfig对应用程序进行动态配置

参考资料 Automating Feature Release using AWS AppConfig Integration with AWS CodepipelineDeploying application configuration to serverless: Introducing the AWS AppConfig Lambda extensionCreate a pipeline that uses Amazon AppConfig as a deployment provider…

秒懂算法 | 搜索基础

本篇介绍了BFS和DFS的概念、性质、模板代码。 01、搜索简介 搜索,就是查找解空间,它是“暴力法”算法思想的具体实现。 暴力法(Brute force,又译为蛮力法):把所有可能的情况都罗列出来,然后逐一检查,从中找到答案。这种方法简单、直接,不玩花样,利用了计算机强大的…

JavaScript 中的 String 类型 模板字面量定义字符串

ECMAScript 6新增了使用模板字面量定义字符串的能力。与使用单引号或双引号不同&#xff0c;模板字面量保留换行字符&#xff0c;可以跨行定义字符串&#xff1a; let str1 早起的年轻人\n喜欢经常跳步;let str2 早起的年轻人喜欢经常跳步;console.log(str1);// 早起的年轻人…

【游戏逆向】游戏玩家技能冷却分析

技能冷却对于不同的游戏有不同的存放方式,而技能冷却的遍历也大多不会和技能的普通属性放在一起,在《在**明月刀》这款游戏中,技能的冷却判断格外重要,因为技能的连贯性对打怪的效率影响很大。 我们需要找一个冷却相对较长的技能用来进行扫描和过滤,一般选择几十秒即可,…

【本周特惠课程】基于GAN的图像增强理论与实践(涵盖图像降噪、色调映射、去模糊、超分辨、修复等方向)...

前言欢迎大家关注有三AI的视频课程系列&#xff0c;我们的视频课程系列共分为5层境界&#xff0c;内容和学习路线图如下&#xff1a;第1层&#xff1a;掌握学习算法必要的预备知识&#xff0c;包括Python编程&#xff0c;深度学习基础&#xff0c;数据使用&#xff0c;框架使用…

Windows扫描工具RunScanner使用实验(21)

实验目的 掌握利用Runscanner扫描和分析电脑&#xff1b;预备知识 RunScanner是一个完全免费的Windows系统工具,您可以用它轻松地将隐藏在您系统中的autostart程序,spyware,adware,主页劫持,未经认证的驱动揪出来,并可以导入和导出报告以帮助别人或获取帮助.目前它可以…

华为OD机试题,用 Java 解【素数之积】问题

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…

C++中的利器——模板

前文本文主要是讲解一下C中的利器——模板&#xff0c;相信铁子们在学完这一节后&#xff0c;写代码会更加的得心应手&#xff0c;更加的顺畅。一&#xff0c;泛型编程想要学习模板&#xff0c;我们要先了解为什么需要模板&#xff0c;我们可以看看下面这个程序。int add(int&a…

MDK Keil5 创建Stm32工程-理论篇(这里以Stm32F103Zet6为例)

一、文件夹创建与文件说明整个工程可以粗略的划分为几个文件夹&#xff1a;BSP底层驱动比如GPIO\Timer等驱动文件CMSIS内核相关的文件Firmware生成的固件下载文件Mycode用户编写的相关文件&#xff0c;主要编写的文件都在这个文件夹里Project工程文件startup芯片启动文件STM32F…

1.C#与.NET简介

目录 一、C#语言及其特点 二、C#与.NET Framework/.NET Core关系 三、C#应用开发 四、案例展示 五、学习环境 一、C#语言及其特点 C#是美国微软公司发布的一种面向对象的&#xff0c;运行于 .NET Framework 和 .NET Core &#xff08;完全开源&#xff0c;跨平台&#xff…

什么是LSM-Tree

前言 十多年前&#xff0c;谷歌发布了大名鼎鼎的"三驾马车"的论文&#xff0c;分别是GFS(2003年)&#xff0c;MapReduce&#xff08;2004年&#xff09;&#xff0c;BigTable&#xff08;2006年&#xff09;&#xff0c;为开源界在大数据领域带来了无数的灵感&#…

unity的安装配置和第一个游戏-unity开学第一课

许多的小伙伴学编程语言其实是因为玩游戏&#xff0c;玩着玩着就想写游戏了&#xff0c;于是开始学习c学习C#学习java&#xff0c;但相比之下C#的操作会更加容易&#xff0c;所以就开始学习unity来编游戏了。这里就就算是unity开学第一课啦-unity的安装配置和第一个游戏。 文章…

Maven项目的创建

目录 1.创建java项目 1.1 新建项目​编辑 2 创建web项目 2.1 新建项目 2.2 启动项目 2.2.1 修改jdk的版本 2.2.2 设置单元测试的版本 2.2.3 删除pluginManagement标签 2.2.4添加web部署插件 2.2.5 启动项目 1.创建java项目 1.1 新建项目 创建resources目录 利用maven…

类模板函数模板从属类型

准备看个项目找实习&#xff0c;边看边学&#xff0c;一看到处都是template 和typename&#xff0c;好几年前学的C都忘记光了&#xff0c;在这里先做个笔记复习一下。template <class T> T abs(T x) {if(x < 0) return -x;return x; } int main() {int x 1;cout <…

PyQt5可视化 7 饼图和柱状图实操案例 ①Qt项目的创建

目录 一、新建Qt项目 二、添加组件和布局 三、添加资源 1. 新建资源文件 2. 添加图标资源 四、frameHead 1. toolBtnGenData 2. toolBtnCounting 3. comboTheme 4. comboAnimation 5. Horizontal Spacer 6. toolBtnQuit 7. 设置toolBtnQuit的功能 8. frameHead的…

设计模式(十六)----结构型模式之代理享元模式

1、概述 定义&#xff1a; 运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似对象的开销&#xff0c;从而提高系统资源的利用率。 2 结构 享元&#xff08;Flyweight &#xff09;模式中存在以下两种状…

CentOS系统安装部署Zabbix

1、LNMP环境部署&#xff1a; 1&#xff09;系统升级&#xff1a; yum update -y 2&#xff09;安装依赖库&#xff1a; yum install -y zlib pcre pcre-devel openssl openssl-devel 3&#xff09;添加用户www&#xff0c;那么也自动创建了用户组&#xff1a;www&#xf…

C/C++开发,无可避免的多线程(篇五).实现自己的线程封装类

一、c11以前的线程封装版本 在本专栏的多线程课题第一篇就说过&#xff0c;c11标准前&#xff0c;实现多线程事务是由调用的<pthread.h>头文件的线程相关功能函数来实现的。 现在通过<pthread.h>的pthread_create、pthread_join、pthread_exit等功能函数来封装一个…

VRRP主备备份

1、VRRP专业术语 VRRP备份组框架图如图14-1所示: 图14-1:VRRP备份组框架图 VRRP路由器(VRRP Router):运行VRRP协议的设备,它可能属于一个或多个虚拟路由器,如SwitchA和SwitchB。虚拟路由器(Virtual Router):又称VRR…

元宇宙、区块链 通俗易懂

什么是区块链&#xff1f;比特币挖矿是什么&#xff1f;元宇宙是什么&#xff1f;Web(万维网)的三权化进化&#xff1a;基于此&#xff0c;介绍下“元宇宙”。1992年&#xff0c;美国作家史蒂芬森在《雪崩》一书中首次提出了“元宇宙(Metaverse)”的概念。元宇宙实际上就是一种…