antv g6 4.x vue 决策树

news/2025/3/6 10:06:00/文章来源:https://www.cnblogs.com/xiaonanxun/p/18754387

原型:https://g6-v4.antv.vision/examples/case/treeDemos/#decisionTree

 

<template><div class="main-content-box"><div id="container"></div></div>
</template><script>
import api from '@/api';
import G6 from '@antv/g6';
import insertCss from 'insert-css';
const colors = {B: '#5B8FF9',R: '#F46649',Y: '#EEBC20',G: '#5BD8A6',DI: '#A7A7A7'
};export default {indexName: 'SubjectDependenceTree',components: {},props: {isTreeDialog: Boolean},data() {return {list: [], //扁平结构的数据(从接口获取)noRepeatList: [], //存放剔除重复值之后的数据
      mockData: {},nodeChildren: [], //单个node子级数据childrenNode: {} //存放子节点点击的node
    };},mounted() {let params = { indexCode: 'POLICY_AWARDS_PUNISH_MANAGE', reportTheme: 0, isFirst: true };this.searchQueryIndexTree(params);},methods: {getInit() {let vm = this;G6.registerNode('flow-rect',{shapeType: 'flow-rect',draw(cfg, group) {const { indexName = '', indexCode, isChild, collapsed, indexCategory, status } = cfg;const grey = '#CED4D9';// background: #0092ee;// color: white;const rectConfig = {width: 202,height: 60,lineWidth: 1,fontSize: 12,fill: '#fff',radius: 4,stroke: grey,opacity: 1};const nodeOrigin = {x: -rectConfig.width / 2,y: -rectConfig.height / 2};const textConfig = {textAlign: 'left',textBaseline: 'bottom'};const rect = group.addShape('rect', {attrs: {x: nodeOrigin.x,y: nodeOrigin.y,...rectConfig}});const rectBBox = rect.getBBox();//科目编码group.addShape('text', {attrs: {...textConfig,x: 8 + nodeOrigin.x,y: 23 + nodeOrigin.y,text: indexCode.length > 23 ? indexCode.substr(0, 23) + '...' : indexCode,fontSize: 12,fill: '#000',opacity: 0.85,cursor: 'pointer'},name: 'name-shape'});//  科目名称const price = group.addShape('text', {attrs: {...textConfig,x: 12 + nodeOrigin.x,y: rectBBox.maxY - 12,text: indexName.length > 10 ? indexName.substr(0, 10) + '...' : indexName,fontSize: 12,opacity: 0.85,fill: '#000'}});// 科目类型group.addShape('text', {attrs: {...textConfig,x: price.getBBox().maxX + 5,y: rectBBox.maxY - 12,text: indexCategory == 1 ? '离线指标' : indexCategory == 2 ? '指标填报' : '自定义',fontSize: 10,fill: '#0092ee',opacity: 0.75}});// rect  展开节点( + -边框)if (cfg.isChild) {group.addShape('rect', {attrs: {x: rectConfig.width / 2 - 8,y: -8,width: 16,height: 16,stroke: 'rgba(0, 0, 0, 0.25)',cursor: 'pointer',radius: 8,fill: '#fff'},// must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item typename: 'collapse-back',modelId: cfg.id});// collpase text(+ -)group.addShape('text', {attrs: {x: rectConfig.width / 2,y: 1,textAlign: 'center',textBaseline: 'middle',text: collapsed ? '+' : '-',fontSize: 16,cursor: 'pointer',fill: 'rgba(0, 0, 0, 0.25)'},// must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item typename: 'collapse-text',modelId: cfg.id});}this.drawLinkPoints(cfg, group);return rect;},//       * 响应节点的状态变化。//  * 在需要使用动画来响应状态变化时需要被复写
          setState(name, value, item) {if (name === 'collapse') {const group = item.getContainer();const collapseText = group.find((e) => e.get('name') === 'collapse-text');if (collapseText) {console.log(value);if (!value) {collapseText.attr({text: '-'});} else {collapseText.attr({text: '+'});}}}},getAnchorPoints() {return [[0, 0.5],[1, 0.5]];}},'rect');G6.registerEdge('flow-cubic',{getControlPoints(cfg) {let controlPoints = cfg.controlPoints; // 指定controlPointsif (!controlPoints || !controlPoints.length) {const { startPoint, endPoint, sourceNode, targetNode } = cfg;const { x: startX, y: startY, coefficientX, coefficientY } = sourceNode ? sourceNode.getModel() : startPoint;const { x: endX, y: endY } = targetNode ? targetNode.getModel() : endPoint;let curveStart = (endX - startX) * coefficientX;let curveEnd = (endY - startY) * coefficientY;curveStart = curveStart > 40 ? 40 : curveStart;curveEnd = curveEnd < -30 ? curveEnd : -30;controlPoints = [{ x: startPoint.x + curveStart, y: startPoint.y },{ x: endPoint.x + curveEnd, y: endPoint.y }];}return controlPoints;},getPath(points) {const path = [];path.push(['M', points[0].x, points[0].y]);path.push(['C', points[1].x, points[1].y, points[2].x, points[2].y, points[3].x, points[3].y]);return path;}},'single-line');const container = document.getElementById('container');const width = container.scrollWidth;const height = container.scrollHeight || 500;const graph = new G6.TreeGraph({container: 'container',width,height,padding: [20, 50],// defaultLevel: 3,defaultZoom: 0.3,// minZoom: 0.3,// maxZoom: 1.5,
        modes: {default: ['zoom-canvas', 'drag-canvas']},fitView: false, //是否启用画布自适应,适配画布大小animate: false, //是否启用全部动画
        defaultNode: {type: 'flow-rect'},// 设置边的参数
        defaultEdge: {type: 'cubic-horizontal',style: {stroke: '#CED4D9'}},layout: {type: 'indented',direction: 'LR',dropCap: false,preventOverlap: true, // 防止节点重叠indent: 300,getHeight: () => {return 40;}}});graph.data(this.mockData[0]);graph.render();graph.fitView(100); //适配视图,自动缩放和平移以适应内容大小,默认留白为 30pxgraph.zoom(0.6); // 设置缩放级别为50%const handleCollapse = async (e) => {this.childrenNode = [];const target = e.target;const id = target.get('modelId');const item = graph.findById(id);const nodeModel = item.getModel();const children = nodeModel.children;if (!children || children.length === 0) {this.childrenNode = nodeModel;let params = {indexCode: nodeModel.indexCode, //科目编码reportTheme: 0, //主题isFirst: false //初始化三层依赖树true,后面展开第四层或往后 false
          };this.addTree(params);if (!nodeModel.children) {nodeModel.children = [];}// 如果childData是一个数组,则直接赋值给parentData.children// 如果是一个对象,则使用parentData.children.push(obj)setTimeout(() => {if (this.nodeChildren && this.nodeChildren.length > 0) {nodeModel.isChild = true;nodeModel.children = this.nodeChildren;nodeModel.collapsed = false;} else {//子级存在单个重复数据nodeModel.isChild = false;nodeModel.children = [];nodeModel.collapsed = true;}item.update(nodeModel);}, 300);} else {nodeModel.collapsed = !nodeModel.collapsed;// graph.updateItem(id, nodeModel);
          item.update(nodeModel);}setTimeout(() => {graph.render();// graph.refresh();// graph.layout();
          item.updatePosition(nodeModel);graph.focusItem(item); //将当前的节点设置为焦点}, 500);};graph.on('collapse-text:click', (e) => {handleCollapse(e);});graph.on('collapse-back:click', (e) => {handleCollapse(e);});this.$nextTick(() => {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);};});},// 展开子结构async addTree(params) {this.list = [];this.nodeChildren = [];const res = await api.queryIndexTree(params);if (res.success) {this.list = res.data;this.nodeChildren = this.comparativeData(); //子级剔除重复数据this.noRepeatList = this.noRepeatList.concat(this.comparativeData()); //剔除重复数据} else {this.$message.error(`${res.message}`);}},// 查询结构树初始化前三层async searchQueryIndexTree(params) {this.list = [];const res = await api.queryIndexTree(params);if (res.success) {this.list = res.data;this.noRepeatList = this.noRepeatList.concat(this.comparativeData()); //剔除重复数据this.mockData = this.toTree(this.noRepeatList); //将扁平化数据转换为树结构this.$nextTick(() => {setTimeout(() => {this.getInit();}, 500);});} else {this.$message.error(`${res.message}`);}},//对比是否存在重复数据,同层级存在重复数据后点击的节点isChild=false,collapsed=false
    comparativeData() {let arr = [];let hasUsefulNode = false;let result = this.list.map((i) => {let one = this.noRepeatList.findIndex((k) => k.indexCode == i.indexCode);if (one < 0) {hasUsefulNode = true;arr.push({id: i.id,indexCode: i.indexCode,indexName: i.indexName,parentId: i.parentId,indexCategory: i.indexCategory, //类型collapsed: !i.isOpen, //控制是否展开isChild: i.isChild // 控制是否有子级
          });}});if (!hasUsefulNode) {let one = this.noRepeatList.find((k) => k.indexCode == this.childrenNode.indexCode);if (one) {one.isChild = false;one.collapsed = true;}}return arr;},//打平数据转换为树结构
    toTree(items) {const tree = []; //存放最终的树状结构const itemMap = {}; //存放每个节点数据for (const item of items) {const { indexCode } = item;itemMap[indexCode] = { ...item, children: [] }; //每个节点增加一个children属性,用来存放子节点
      }// 遍历所有节点,将每个节点放到其父节点的children数组中for (const item of items) {const { indexCode, parentId } = item;// 如果是根节点,则直接放入结果数组中if (indexCode == parentId) {//if (parentId == null || parentId == 0) {
          tree.push(itemMap[indexCode]);} else {// 如果不是根节点,则将当前节点放入其父节点的children数组中// 子元素的parentId 等于  父节点的id  itemMap[parentId] 父节点//itemMap[indexCode] 当前节点if (itemMap[parentId]) itemMap[parentId].children.push(itemMap[indexCode]);}}return tree;}}
};
</script>
<style lang="scss" scoped>
.g6-component-tooltip {background-color: rgba(0, 0, 0, 0.65);padding: 10px;box-shadow: rgb(174, 174, 174) 0px 0px 10px;width: fit-content;color: #fff;border-radius: 4px;
}
</style>

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20242825 2024-2025-2 《网络攻防实践》第一周作业

@目录一、知识点梳理与总结二、攻防环境搭建过程(一)前提知识以及拓扑结构1.1 相关软件总结1.2 拓扑结构图(二)网络配置过程2.1 VMnet1配置2.2 VMnet8配置(三)各虚拟机配置及测试过程3.1 kali攻击机配置3.1.1 在kali安装时遇到问题3.1.2 解决问题重新安装kali3.1.3 安装完…

修改el-table样式之cell-class-name

修改el-table样式有好几种方式,有修改行,列,表头,这里讲的是修改列,且是列中cell的样式,因为表格是前任封装好的,无法在内部随意修改加类名,故无法使用cell-style单独完成,这里介绍cell-class-name属性完成 原图: 表格被前人封装为超出一定长度显示省略号,这里测试要…

C6678学习笔记(2)启动模式设置

拨码开关和跳线接法 跳线接法 参考文献:TMDXEVM6678L_Technical_Reference_Manual_2V00.pdf(在附赠的光盘中) 需要注意的是网上搜的参考手册有部分是第一版的,PCB布局是有些差异的,例如LED灯的位置,以光盘中的使用手册为准。跳线是用来选择串口的,如图的这种接法选择的是…

基于CANoe的HTTP节点仿真与测试实践

1. 背景在汽车电子系统测试中,CANoe作为主流的仿真测试工具,常需与云端服务器、第三方软件或物联网设备进行交互。随着CANoe与外部软件、服务器或设备交互越来越多,直接使用Socket进行通信往往不能满足使用需求,依托于CANoe 的连接功能集(Connectivity Feature Set),以及…

Web前端入门第 16 问:学会使用开发者工具调试 HTML 页面

HELLO,这里是大熊学习前端开发的入门笔记。 本系列笔记基于 windows 系统。有没有好奇,前面文章中的截图是怎么来的?怎样查看 HTML 的渲染结果? Web 开发者的照妖镜 曾经火狐( Firefox )是 Web 前端开发者最喜爱的浏览器,因为他家有一个神器 firebug 方便调试前端代码。…

Web前端入门第 17 问:前端开发编辑器及插件推荐

HELLO,这里是大熊学习前端开发的入门笔记。 本系列笔记基于 windows 系统。虽然说 Web 前端开发用记事本也能玩,但正常的开发者绝不用记事本玩(大佬除外)。 想想要用记事本扣一个淘宝、京东,那场景可真是美呆了。 一个好的编辑器,绝对可以事半功倍的。 编辑器可以提供哪些…

Web前端入门第 15 问:学会查阅 HTML 文档

HELLO,这里是大熊学习前端开发的入门笔记。 本系列笔记基于 windows 系统。HTML的魔法世界,多姿多彩,千变万化。 授人以鱼不如授人以渔,文档阅读是开发者必备的技能,毕竟代码出现 BUG,也要知道为什么会出现 BUG 吧。 就像车辆使用手册一样,多翻翻使用手册,总会发现一些…

Web前端入门第 12 问:HTML 常用属性一览

HELLO,这里是大熊学习前端开发的入门笔记。 本系列笔记基于 windows 系统。 HTML 常用属性大约 70 个,是否又头大了?脸上笑嘻嘻,心里嘛...嘿嘿... 温馨提示:属性不用死记硬背,多练多写慢慢就记住了。 全局常用属性 全局属性为 HTML 元素的通用属性,可以在任何元素上使用…

Web前端入门第 8 问:HTML !DOCTYPE 申明有何用处?如果没有此申明有什么问题?

HELLO,这里是大熊学习前端开发的入门笔记。 本系列笔记基于 windows 系统。先电脑端浏览器打开任何一个网页,比如百度。 再用 ctrl + u 快捷键即可查看源码,瞅瞅第一行代码,是不是都是 <!DOCTYPE xxx> 开头。 是否好奇这这行代码有嘛用? DOCTYPE 语法规则声明必须是…

Web前端入门第 9 问:HTML 块级元素,内联块元素,内联元素三者有什么区别?

HELLO,这里是大熊学习前端开发的入门笔记。 本系列笔记基于 windows 系统。HTML 中的元素根据其默认的 显示类型 主要分为三类:块级元素、内联元素 和 内联块元素。 它们的核心区别在于布局行为和样式控制的支持程度。 块级元素 块级元素(Block Elements)是指在 HTML 中以块…

Easyexcel(1-注解使用)

EasyExcel 是阿里巴巴开源的一个轻量级 Excel 操作框架,专为 Java 开发者设计,支持读取和写入 Excel 文件。它使用注解来简化数据解析和导出工作,特别适用于复杂的 Excel 文件结构和大数据量处理。版本依赖 <dependency><groupId>com.alibaba</groupId>&l…

MES收料批号接口,列名FID无效

原因:主键字段名默认设置了FID,如下图。 解决:将主键字段名修改为实际的主键字段名称即可。