uniapp 端开发 echarts 树结构图

news2024/11/15 12:15:53

实现效果 : 

1. 在uniapp 中写echarts 树结构图需要使用  
 

<script module="echarts" lang="renderjs">

否则会无法显示echarts 图形 

rebderjs 代码  引入了 /static/echarts.min.js
是在 ECharts 在线构建 定制你的echarts

<template>
	<view>
		<view class="echarts" :prop="option" :change:prop="echarts.update"></view>
	</view>
</template>

<script>
	export default {
		name: 'Echarts',
		props: {
			option: {
				type: Object,
				required: true
			}
		},

		methods: {
           // echarts 点击跳转的
			onViewClick(options) {
				console.log("已进入");
				console.log(options);
				if (null !== options.test?.lawId && undefined !== options.test?.lawId) {

					uni.navigateTo({
						url: ' ', // 替换为你的详情页面路径和查询参数
						fail: function(res) {
							console.error('页面跳转失败:', res);
						}
					});
				} else {
					console.log(options);
				}

			}
		}
	}
</script>

<script module="echarts" lang="renderjs">
	import _ from 'lodash';

	export default {
		data() {
			return {
				chart: null,
				options: "",
				fontSize: 12,
				symbolSize: 7,
				paddingH: 8,
				paddingW: 4,
				height: 20,
				width: 300,
				width2: 80,
				startTime: null, // 用于记录开始时间
				debouncedResize: _.debounce(this.resize, 500), // 防抖动处理
				elesCounts: 0,
				loading: true

			}
		},
		mounted() {
			if (typeof window.echarts === 'object') {
				this.init();

			} else {
				// 动态引入类库
				const script = document.createElement('script')
				// script.src = './static/echarts.min.js'
				script.src = './static/echarts/echarts1.min.js'
				script.onload = this.init
				document.head.appendChild(script);
				//这两行代码解决在小程序中echarts点击失效问题
			}

		},
		methods: {
			/**
			 * 初始化echarts
			 */
			init() {


				echarts.env.touchEventsSupported = true;
				echarts.env.wxa = false;
				echarts.env.canvasSupported = false;
				echarts.env.svgSupported = true;
				echarts.env.domSupported = true;
				//渲染前
				this.loading = true;

				this.chart = echarts.init(this.$el, {
					renderer: 'canvas'
				});


				if (this.loading) {
					this.chart.showLoading('default', {
						text: '数据加载中...',
						color: '#333',
						textColor: '#666',
						maskColor: 'rgba(255, 255, 255, 0)',
						zlevel: 0
					});
				}
				
				 // 延迟执行以确保图表渲染完成
				        setTimeout(() => {
				            this.chart.hideLoading();
				           
				        }, 1000); 
 
				this.update(this.option);
	// 监听图表渲染完成事件
						 


			},

			getLeftNodeChildren(zoom, children) {
				this.symbolSize = Math.min(7, this.symbolSize * zoom);

				return children.map(child => ({
					...child,
					label: {
						...child.label,
						fontSize: Math.max(2, Math.min(12, this.fontSize * zoom)),
						padding: [Math.min(4, this.paddingW * zoom), Math.min(8, this.paddingH * zoom)],
						height: this.height,
						width: this.width
					},
					symbolSize: this.symbolSize,
					children: child.children ? this.getLeftNodeChildren(zoom, child.children) : [],
				}));
			},

			/**
			 * 监测数据更新
			 * @param {Object} option
			 */
			update(option) {

				if (this.chart) {
					// 因App端,回调函数无法从renderjs外传递,故在此自定义设置相关回调函数
					if (option) {
						this.options = option
						// tooltip
						if (option.tooltip) {
							console.log(option.tooltip.position);
							// 判断是否设置tooltip的位置
							if (option.tooltip.positionStatus) {
								option.tooltip.position = this.tooltipPosition()

							}
							// 判断是否格式化tooltip
							if (option.tooltip.formatterStatus) {
								option.tooltip.formatter = this.tooltipFormatter(option.tooltip.formatterUnit, option
									.tooltip.formatFloat2, option.tooltip.formatThousands)
							}
						}


						// 设置新的option
						this.chart.setOption(option, option.notMerge);

						// 确保在初始化后禁用触摸事件支持
						if (typeof this.chart === 'object') {

							this.chart.getZr().handler.touchEventsSupported = false;
							this.chart.getZr().handler.wxa = false;

						}


						// 添加条件语句来确保属性已经存在
						if (this.chart._chartsViews && this.chart._chartsViews[0] && this.chart._chartsViews[0]._data) {
							let elesArr = Array.from(new Set(this.chart._chartsViews[0]._data._graphicEls));
							this.elesCounts = elesArr.length;

							console.log(elesArr.length);
							if (elesArr.length >= 130) {
								option.series[0].top = '-600px';
								option.series[0].left = '-600px';

								console.log(88888);
								// console.log(111111);
								this.chart.resize({
									width: 1200,
									height: 5000
								});
							} else {
						
								this.resize(); // 使用防抖动的 resize'
								
								
							}


						}
						
					
						// this.chart.resize({
						// 	width: 800,


						// 	height: 400
						// });
						this.chart.off("click")

						//跳转前先解绑,防止重复跳转
						this.chart.off('click');
						//	使用 ECharts 内部点击事件
						this.chart.on("click", params => {
							console.log(params.data);
							// 判断点击的是否是树图的节点
							if (params.componentType === 'series' && params.seriesType === 'tree') {
								// 阻止事件冒泡

								params.event.event.stopPropagation();
								// 处理点击事件
								console.log('Tree节点被点击,数据为:', params.data);
							}

							this.$ownerInstance.callMethod('onViewClick', {
								test: params.data
							})
						});



						this.chart.on('treeroam', this.handleTreeRoam);


					}

				}
			},

			// 使用 _.throttle 包装 handleTreeRoam 函数,确保其每300毫秒最多执行一次
			handleTreeRoam: _.throttle(function(res) {
				const opt = this.options;
				const zoom = res.zoom || 1;
				console.log(zoom);
				if (zoom == 1) {
					this.chart.setOption(this.options);
					return;
				}
				console.log(zoom);
				// 更新字体大小
				const fontSize = Math.max(2, Math.min(12, this.fontSize * zoom));
				this.fontSize = fontSize;
				const padding = [Math.min(4, this.paddingW * zoom), Math.min(8, this.paddingH * zoom)];
				this.paddingW = padding[0];
				this.paddingH = padding[1];
				const heights = Math.min(30, this.height * zoom);
				this.height = heights;

				const widths = Math.min(300, this.width * zoom);
				this.width = widths;


				const widths2 = Math.min(80, this.width2 * zoom);
				this.width2 = widths2;
				const newOption = {
					...opt,
					series: [{
						...opt.series[0],
						label: {
							...opt.series[0].label,
							fontSize: fontSize,
							padding: padding,
						},
						leaves: {
							...opt.series[0].leaves,
							label: {
								...opt.series[0].leaves.label,
								fontSize: fontSize,
								padding: padding,
							},
						},
						data: opt.series[0].data.map(node1 => ({
							...node1,
							label: {
								...node1.label,
								fontSize: fontSize,
								padding: padding,
								height: heights,

							},
							symbolSize: this.symbolSize,
							children: node1.children.map(node2 => ({
								...node2,
								label: {
									...node2.label,
									fontSize: fontSize,
									padding: padding,
									height: heights,
									width: widths2
								},
								symbolSize: this.symbolSize,
								children: this.getLeftNodeChildren(
									zoom, node2.children),
							})),
						})),
					}],
				};
				this.options = newOption;


				// this.chart.setOption(this.options, true);
				if (zoom != 1) {
					if (this.elesCounts > 130) {
						const opt = this.options.series[0].data[0];
						const height = opt.label.height;
						console.log(height);
						if (opt.label.height < 20 && opt.label.height >= 10) {
							this.chart.resize({
								width: 900,
								height: 3800
							});
						} else {
							this.chart.resize({
								width: 450,
								height: 2500
							});
						}
					} else {
						this.resize();
					}
					this.chart.setOption(this.options, true);
				}

			}, 1000), // 300 毫秒节流



			 
			// 使用 _.debounce 包装 setOption 函数,确保其在 300 毫秒后执行
			resizeDebounce: _.debounce(function() {
				if (this.chart) {
					 
					this.resize();
				}
			}, 300), // 300 毫秒防抖

			// 使用 _.debounce 包装 setOption 函数,确保其在 300 毫秒后执行
			debouncedSetOption: _.debounce(function() {
				if (this.chart) {
					console.log(99999);
					
				}
			}, 300), // 300 毫秒防抖

			resize() {
				const opt = this.options.series[0].data[0];

				let elesArr = Array.from(new Set(this.chart._chartsViews[0]._data._graphicEls));
				let dep = this.chart._chartsViews[0]._data.tree.root.height; // 获取树高
				let layer_height = 10; // 层级之间的高度
				let layer_width = 25; // 兄弟节点之间的距离

				const height = opt.label.height;
				const elesCount = elesArr.length;


                // dep 是节点深度   elesCount 是节点的数量  这里根据节点深度和数量进行设置
                // 根据自己需求完善 
				if (dep == 4) {
					if (elesCount < 10) {

						// 调整高度和宽度逻辑
						if (opt.label.height == 30) {
							layer_height = 130;
							layer_width = 120;
						} else if (opt.label.height < 25 && opt.label.height >= 20) {
							layer_height = 130;
							layer_width = 110;
						} else if (opt.label.height < 20 && opt.label.height >= 15) {
							layer_height = 130;
							layer_width = 100;
						} else if (opt.label.height < 15 && opt.label.height >= 10) {
							layer_height = 130;
							layer_width = 80;
						} else if (opt.label.height < 10 && opt.label.height > 5) {
							layer_height = 130;
							layer_width = 70;
						} else {
							layer_height = 130;
							layer_width = 70;
						}

						console.log('opt is 4 and elesCount is less than 10');
					} 

				let newHeight = layer_height * elesArr.length;
				let currentWidth = layer_width * (elesArr.length - 1) || layer_width;
				let newWidth = Math.max(currentWidth, layer_width);
				console.log(newWidth);
				console.log(newHeight);
				// 保持图表中心在可视区域

				this.chart.resize({
					width: newWidth,
					height: newHeight
				});


			},



			/**
			 * 设置tooltip的位置,防止超出画布
			 */
			tooltipPosition() {
				return (point, params, dom, rect, size) => {
					//其中point为当前鼠标的位置,size中有两个属性:viewSize和contentSize,分别为外层div和tooltip提示框的大小

					let x = point[0]
					let y = point[1]
					let viewWidth = size.viewSize[0]
					let viewHeight = size.viewSize[1]
					let boxWidth = size.contentSize[0]
					let boxHeight = size.contentSize[1]
					let posX = 0 //x坐标位置
					let posY = 0 //y坐标位置
					if (x < boxWidth) { //左边放不开
						posX = 5
					} else { //左边放的下
						posX = x - boxWidth
					}
					if (y < boxHeight) { //上边放不开
						posY = 5
					} else { //上边放得下
						posY = y - boxHeight
					}
					return [posX, posY]
				}
			},


		}
	}
</script>

<style lang="scss" scoped>
	.echarts {
		width: 100vh;
		height: 100vh;
	}




	.p-line-charts-out {
		height: 100%;
		width: 100%;

		.p-line-charts {
			width: 100% !important;
			height: calc(100% - 25px) !important;
		}
	}
</style>

echarts 展示页面 :  基本代码调试一下就可以了

<view ref="echartsContainer">
					

					<echarts ref="echarts" :option="option"  style="height: 100vh; width: 100vw;">
					
					
					
					</echarts>
<script >
	
	import echarts from '@/pages/userCenter/business.vue';


convertToTreeData(data) {
				return {
					tooltip: {
						trigger: 'item',
						triggerOn: 'mousemove',
						
					},
					 
					series: [{

						type: 'tree',
					
						scaleLimit: {
							min: 0.5,
							max: 2
						},
						data: [data],
						top: '5%',
						left: '3%',
						bottom: '5%',
						right: '10%',
						
						initialTreeDepth: -1,
						roam: true,
						zoom: 1,
						symbolSize: 1,

						label: {
							fontSize: 9,
							position: 'right',
							show: true,
							borderRadius: 5,
							borderWidth: 1,
							verticalAlign: 'middle',
							align: 'center',
							color: '#fff'
						},
						leaves: {
							label: {
								position: 'right',
								verticalAlign: 'middle',
								align: 'left',
								fontSize: 12, // 初始字体大小
								padding: [4, 8], // 初始内边距
							},
						},
						lineStyle: {
							color: '#ccc',
							width: 1.5,
							type: 'solid'
						},
						emphasis: {
							disabled: true,
							focus: 'ancestor'
						},
						// 当节点大于100 时 关闭动画
					
						containLabel: true,
						
						
					}]
				};
			},

</script>

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

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

相关文章

001 RabbitMQ入门及安装

RabbitMQ入门及安装 文章目录 RabbitMQ入门及安装1.介绍1.AMQP和JMS2.目前主流的消息队列 2.安装1.Linux安装1.1 安装erlang1.2 RabbitMQ安装 2.Docker安装 3.核心组件 1.介绍 RabbitMQ是实现了高级消息队列协议&#xff08;AMQP&#xff09;的开源消息代理软件&#xff08;亦…

嵌入式音视频开发:探索多领域的融合与创新

摘要&#xff1a; 本文深入探讨了嵌入式音视频开发领域。从嵌入式系统的基础概念入手&#xff0c;阐述了其在音视频领域的独特地位。详细介绍了嵌入式音视频开发中涉及的硬件组件&#xff0c;如处理器、编解码器、存储设备等。分析了音视频编解码技术&#xff0c;包括常见的编解…

空间数据库概述

空间数据库简介 空间数据库是 地理信息系统 在计算机物理存储介质中存储的&#xff0c;与GIS应用相关的地理空间数据的总和。一般以一系列特定结构的文件形式组织后存储在介质上。 空间数据库的特点 可以存储、处理空间数据相比普通数据库提供更多、更复杂的数据类型以及更多…

[SWPU2019]Web1 超详细教程

老规矩先看源码&#xff0c;没找到啥提示&#xff0c;后面就是登录口对抗 弱口令试了几个不行&#xff0c;就注册了个账户登录进去 可以发布广告&#xff0c;能造成xss&#xff0c;但是没啥用啊感觉 查看广告信息的时候&#xff0c;注意到url当中存在id参数&#xff0c;可能存…

Leetcode面试经典150题-134.加油站

解法都在代码里&#xff0c;不懂就留言或者私信 class Solution {public int canCompleteCircuit(int[] gas, int[] cost) {/**如果只有一个加油站&#xff0c;那它本来就在那个为止&#xff0c;0就是它的编号?但是这只是你的想象&#xff0c;题目有个变态规定&#xff0c;自…

【linux】进程控制(2)

3. 进程等待 1. 是什么 通过系统调用 wait/waitpid 对子进程的退出状态进行检测和回收的功能 2. 为什么 僵尸进程无法杀死&#xff0c;通过进程等待来杀掉它&#xff0c;进而解决内存泄漏的问题 &#xff08;一&#xff09;进程等待的方法 a. wait : 代码 wait : 等待任意一…

解锁SAP数据的潜力:SNP Glue与SAP Datasphere的协同作用

在各种文章中&#xff0c;我们研究了客户如何利用SNP Glue与基于云的数据仓库和数据湖相结合&#xff0c;以充分利用其SAP数据。SNP Glue 通过高性能集成解决方案帮助客户解锁 SAP 数据孤岛。例如&#xff0c;可以使用SNP Glue先进的增量捕获&#xff08;CDC&#xff09;近乎实…

【Linux 报错】Ubuntu 20.04.5 LTS报错:“E: Unable to locate package xx”

问题描述&#xff1a; 在使用 &#xff08;Ubuntu 20.04.5 LTS&#xff09;学习 Linux 时&#xff0c;想要安装 tree 命令&#xff0c;出现下面的报错&#xff1a; rootiZwz9asjf1ddlt6fy1ebqpZ:~# apt install tree Reading package lists... Done Building dependency tree…

蓝光3D扫描仪用于小尺寸精密注塑零件三维检测

在现代精密制造领域&#xff0c;微小型零件的加工和检测依然极具挑战。无论是微型机械零件、电子元器件&#xff0c;汽车注塑件&#xff0c;还是高端医疗器械部件&#xff0c;制造商都必须确保零件尺寸符合设计要求。传统的检测方法已无法满足日益严苛的要求&#xff0c;企业亟…

828华为云征文 | Flexus X的力量,驱动Halo博客在云端飞驰

前言 华为云Flexus云服务器 X实例&#xff0c;以卓越性能与灵活配置&#xff0c;为Halo博客搭建起梦想的云端舞台。在这个828企业上云节节日里&#xff0c;华为云Flexus云服务器 X实例不仅提供了稳定高效的运行环境&#xff0c;更助力Halo博客实现内容创作的无限可能。无论是流…

240912-通过Ollama实现网站知识总结

A. 最终效果 B. 准备工作 报错: USER_AGENT environment variable not set, consider setting it to identify your requests.-CSDN博客 C. 完整代码 # https://coreyclip.github.io/Ollama-Web-Summaries/import os os.environ[USER_AGENT] Mozilla/5.0 (Windows NT 10.…

docker安装部署Canal-监听mysql

文章目录 安装和配置Canal1.开启MySQL主从1.1.开启binlog1.2.设置用户权限 2.安装Canal2.1.创建网络2.3.安装Canal 遇到的问题 安装和配置Canal 下面我们就开启mysql的主从同步机制&#xff0c;让Canal来模拟salve 1.开启MySQL主从 Canal是基于MySQL的主从同步功能&#xff…

cheat:在终端中,在线查询Linux命令

cheat.sh 是一个命令查询网站&#xff0c;在终端中也能够使用。特点是返回简单易懂的代码示例和注解&#xff0c;可以帮助用户快速了解命令的使用方法。 ​​ 1.语法 curl cheat.sh/command2.示例 查询 ls 命令的用法 curl cheat.sh/ls查询 chmod 命令的用法 curl cheat.…

sqlite在Windows环境下安装、使用、node.js连接

sqlite在Windows环境下安装、使用、node.js连接 前言&#xff1a;2024年9月10日 1. 下载安装 sqlite 的安装非常简单 去官网下载对应压缩包 将两个压缩包解压&#xff0c;并将解压出来的文件放在同一目录下 将上面的目录路径配置到环境变量 path 中 2. 执行 sql sqlite …

Day7 | Java框架 | SpringMVC

Day7 | Java框架 | SpringMVC SpringMVC简介SpringMVC 概述入门案例入门案例工作流程分析Controller 加载控制与业务bean加载控制&#xff08;SpringMVC & Spring&#xff09;PostMan 请求与响应请求映射路径请求方式&#xff08;不同类型的请求参数&#xff09;&#xff1…

基于Linux文件编程实现处理Excel表格的数据

目录 前言 整体的代码框架 如何读取数据文件的数据 read_line 如何处理读取到的数据 process_data 运行结果 总结 前言 本文是基于Linux文件编程的一个小实验&#xff0c;用文件IO来读取Excel表格的数据&#xff0c;处理后写入另一个文件&#xff0c;本文只是对文件IO的…

一些硬件知识(二十二)

二极管&#xff08;Diode&#xff09;伏安特性、技术参数和项目中的应用 在正向偏置下&#xff0c;二极管呈现出良好的导电性能&#xff0c;可以允许电流通过&#xff1b;而在反向偏置下&#xff0c;二极管具有很高的阻断能力&#xff0c;几乎不允许电流通过。这是由构成二极管…

CC工具箱使用指南:【字段计算器学习版】

一、简介 这个工具算是Pro自带的字段计算器的扩展版。 工具预制了几种计算模式&#xff0c;通过可视化操作&#xff0c;帮你自动生成代码。 生成代码后&#xff0c;可以直接运行&#xff0c;也可以将代码复制到Pro自带的字段计算器中进行计算。 总之&#xff0c;这是给不会…

【CanMV K230 AI视觉】 人体检测

【CanMV K230 AI视觉】 人体检测 人体检测 动态测试效果可以去下面网站自己看。 B站视频链接&#xff1a;已做成合集 抖音链接&#xff1a;已做成合集 人体检测 人体检测是判断摄像头画面中有无出现人体&#xff0c;常用于人体数量检测&#xff0c;人流量监控以及安防监控等。…

研1日记9

1.理解conv1d和conv2d a. 1和2处理的数据不同&#xff0c;1维数据和图像 b. 例如x输入形状为(32,19,512)时&#xff0c;卷积公式是针对512的&#xff0c;而19应该变换为参数中指定的输出通道。 2.“SE块”&#xff08;Squeeze-and-Excitation Block&#xff09;它可以帮助模…