首页IT科技gh树形数据(G6绘制树形图(自定义节点、自定义边、自定义布局))

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

时间2025-07-30 19:31:31分类IT科技浏览9777
导读:1 设计节点 在 registerNode 中定义所有的节点...

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>
声明:本站所有文章                         ,如无特殊说明或标注                       ,均为本站原创发布                  。任何个人或组织,在未征得本站同意时                     ,禁止复制             、盗用                            、采集            、发布本站内容到任何网站        、书籍等各类媒体平台                           。如若本站内容侵犯了原著者的合法权益                           ,可联系我们进行处理        。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
搜索引擎的使用技巧和网站优化的技巧(如何提高网站排名和让搜索引擎更好地为您服务) uniapp跳转页面(记录–uniapp 应用APP跳转微信小程序)