uniapp x + vue3 实现echarts图表

一、引入echarts组件

在Dcloud插件市场下载echarts插件:https://ext.dcloud.net.cn/plugin?id=4899

下载解压后的文件结构如下图所示:

1、将提供的 components 文件复制到你项目对应的components目录中。

目录结构示意图如下:

2、将提供的static / app下的文件复制到你项目对应的 static 目录中。

3、打开echarts官网(https://echarts.apache.org/zh/download.html),下载定制图表。

下载后得到echarts.min.js文件,替换原插件中的echarts.min.js(存放于static文件夹下)。

二、引入并实现Echarts图表

1、引入,参考:https://gitee.com/liangei/lime-echart#vue3

2、实现

父组件:

html 复制代码
<CustomEcharts 
    v-if="progressData.course_finish_data" 
	:dataList="progressData.course_finish_data"
	@getFinishIds="getFinishIds"
/>
javascript 复制代码
<script setup>
    import CustomEcharts from "./components/customEcharts.uvue";
    
    const getFinishIds = async (val:string) => {
		console.log(val, '获取的ids')
	}
</script>

子组件:

html 复制代码
<template>
	<view class="chart_content_item">
		<LEchart ref="chartRef"></LEchart>
	</view>
</template>

<script lang="ts" setup>
import LEchart from "./l-echart/l-echart.vue";
import { ref, onMounted, watch } from "vue"
const echarts = require('../static/echarts.min.js')
const chartRef = ref(null);
const chartInstance = ref(null); // 保存图表实例

const props = defineProps({
	dataList: Array
});
const emits = defineEmits(['getFinishIds']); // 定义自定义事件

const new_data = Object.values(props.dataList).map(item => ({
	value: item.finish_num,
	name: item.title,
	ids: item.finish_id_str,
	// 可以添加其他需要传递的数据
	itemData: item
}))

const pieOption = {
	tooltip: {
		trigger: 'item',
		formatter: function(params) {
			return `${params.name}: \n ${params.value}人`;
		}
	},
	legend: {
		top: '5%',
		left: 'center'
	},
	series: [
		{
			name: '课程完成情况',
			type: 'pie',
			radius: ['40%', '70%'], // 饼图的半径
			center: ['50%', '90%'], // 饼图的中心(圆心)坐标,[横坐标,纵坐标]。
			startAngle: 180, // 起始角度,支持范围[0, 360]
			endAngle: 360, // 结束角度,自动计算
			itemStyle: {
				color: function(params) {
					const colorList = [
						'#0ca8df', '#ffd10a', '#fb628b',
						'#785db0', '#5070dd', '#b6d634',
						'#56597a', '#ff9a4d'
					];
					return colorList[params.dataIndex % colorList.length];
				}
			},
			// data: new_data
			data: [
					{ value: 1048, name: '完成1-3门课程人数', ids:"1" },
					{ value: 735, name: '完成3-6门课程人数', ids:"1,2" },
					{ value: 580, name: '完成6-9门课程人数', ids:"3,4" }
				],
			// 高亮样式
			emphasis: {
				itemStyle: {
					shadowBlur: 10,
					shadowOffsetX: 0,
					shadowColor: 'rgba(0, 0, 0, 0.5)'
				},
				label: {
					show: true,
					fontSize: '16',
					fontWeight: 'bold'
				}
			},
			label: {
				formatter: '{b}: {c}人 ({d}%)',
				fontSize: 12
			}
		}
	]
};

// 初始化图表
const initChart = () => {
	if (!chartRef.value) return;
	
	chartRef.value.init(echarts, (chart) => {
		chartInstance.value = chart;
		chart.setOption(pieOption);
		
		// 绑定点击事件
		bindChartEvents(chart);
	});
};

// 绑定图表事件
const bindChartEvents = (chart) => {
	// 监听饼图点击事件
	chart.on('click', function(params) {
		const clickedData = params.data; // 获取点击项的数据
		const ids = clickedData.ids; // 获取ids
		emits('getFinishIds', ids); // 传参
	});
	
	// 监听其他事件(可选)
	chart.on('mouseover', function(params) {
		// 鼠标悬停事件
		console.log('鼠标悬停:', params.data);
	});
	
	chart.on('mouseout', function(params) {
		// 鼠标移出事件
		console.log('鼠标移出');
	});
};

onMounted(() => {
	setTimeout(() => {
		initChart();
	}, 300);
});

// 监听数据变化
watch(() => props.dataList, (newData) => {
	if (!chartInstance.value) return;
	
	// 更新数据
	const updatedData = Object.values(newData).map(item => ({
		value: item.finish_num,
		name: item.title,
		ids: item.finish_id_str,
		itemData: item
	}));
	
	// 更新图表
	chartInstance.value.setOption({
		series: [{
			data: updatedData
		}]
	});
}, { deep: true });

// 监听配置变化
watch(() => pieOption, (newOption) => {
	if (chartInstance.value) {
		chartInstance.value.setOption(newOption);
	}
}, { deep: true });

// 暴露方法给父组件
defineExpose({
	getSelectedData: () => {
		if (!chartInstance.value) return null;
		// 可以通过其他方式获取当前选中的数据
	},
	refreshChart: () => {
		if (chartInstance.value) {
			chartInstance.value.resize();
		}
	}
});
</script>

<style lang="scss" scoped>
.chart_content_item {
	width: 100%;
	height: 150px;
}
</style>

最终实现效果:

相关推荐
EricLee2 小时前
2025 年终总结 - Agent 元年
前端·人工智能·后端
xuyuan19982 小时前
超越Selenium:自动化测试框架Cypress在现代前端测试中的卓越实践(windows版本)环境搭建
前端·windows·cypress
高山上有一只小老虎3 小时前
SpringBoot项目集成thymeleaf实现web
前端·spring boot·后端
求梦8203 小时前
前端八股文【CSS核心面试题库】
前端·css·面试
算法小菜鸟成长心得3 小时前
记录自己第一次将React 编写的前端部署到服务器,实现外网访问
服务器·前端·react.js
怒放的生命19914 小时前
pnpm + Monorepo 使用教程(集成 Vue 3 项目)
前端·vue.js·pnpm·monorepo·前端工程化
佛系打工仔9 小时前
绘制K线第二章:背景网格绘制
android·前端·架构
明天好,会的10 小时前
分形生成实验(五):人机协同破局--30万token揭示Actix-web状态管理的微妙边界
运维·服务器·前端
C_心欲无痕11 小时前
nginx - alias 和 root 的区别详解
运维·前端·nginx