本篇文章主要讲解如何使用 SpringBoot+Thymeleaf+Echarts、以及 SpringBoot+VUE3.0+Echarts 两种方式,实现 Web 应用中的图标显示功能。

一、Echarts 概述

ECharts是一款基于JavaScript数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。ECharts最初由百度团队开源,并于2018年初捐赠给Apache基金会,成为ASF孵化级项目。

官网地址:Apache ECharts

官方文档地址:快速上手 - 使用手册 - Apache ECharts

官方案例地址:Examples - Apache ECharts

二、SpringBoot+Thymeleaf+Echarts

2.1 数据准备

本案例以某高校某系的 2021-2023 年考研数据为基础显示相应的数据统计图,数据库表如下:

DROP TABLE IF EXISTS `exam_stat`;
CREATE TABLE `exam_stat` (
  `id` int NOT NULL AUTO_INCREMENT,
  `exam_year` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, -- 考研年份
  `college` varchar(50) DEFAULT NULL, -- 学院
  `major` varchar(50) DEFAULT NULL, -- 专业
  `total_num` int DEFAULT NULL, -- 专业总人数
  `exam_num` int DEFAULT NULL, -- 参加考试的人数
  `online_num` int DEFAULT NULL, -- 上线的人数
  `pass_num` int DEFAULT NULL,  -- 录取的人数
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb3;

-- ----------------------------
-- Records of exam_stat
-- ----------------------------
INSERT INTO `exam_stat` VALUES ('1', '2021', '计算机学院', '计算机科学与技术', '50', '6', '5', '10');
INSERT INTO `exam_stat` VALUES ('2', '2021', '计算机学院', '自动化', '45', '17', '8', '6');
INSERT INTO `exam_stat` VALUES ('3', '2021', '计算机学院', '软件工程', '50', '13', '8', '4');
INSERT INTO `exam_stat` VALUES ('4', '2021', '计算机学院', '轨道交通信号控制', '39', '20', '9', '4');
INSERT INTO `exam_stat` VALUES ('5', '2021', '计算机学院', '软件工程(专升本)', '66', '10', '4', '2');
INSERT INTO `exam_stat` VALUES ('6', '2021', '计算机学院', '物联网工程', '37', '8', '1', '0');
INSERT INTO `exam_stat` VALUES ('7', '2022', '计算机学院', '计算机科学与技术', '135', '18', '7', '4');
INSERT INTO `exam_stat` VALUES ('8', '2022', '计算机学院', '自动化', '48', '16', '9', '7');
INSERT INTO `exam_stat` VALUES ('9', '2022', '计算机学院', '软件工程', '195', '57', '20', '5');
INSERT INTO `exam_stat` VALUES ('10', '2022', '计算机学院', '轨道交通信号控制', '35', '6', '6', '4');
INSERT INTO `exam_stat` VALUES ('11', '2022', '计算机学院', '物联网工程', '41', '19', '4', '1');
INSERT INTO `exam_stat` VALUES ('12', '2023', '计算机学院', '计算机科学与技术', '134', '21', '9', '4');
INSERT INTO `exam_stat` VALUES ('13', '2023', '计算机学院', '自动化', '50', '28', '13', '8');
INSERT INTO `exam_stat` VALUES ('14', '2023', '计算机学院', '软件工程', '176', '47', '20', '10');
INSERT INTO `exam_stat` VALUES ('15', '2023', '计算机学院', '轨道交通信号控制', '33', '15', '5', '2');
INSERT INTO `exam_stat` VALUES ('16', '2023', '计算机学院', '物联网工程', '84', '15', '3', '1');
INSERT INTO `exam_stat` VALUES ('17', '2023', '计算机学院', '网络空间安全', '50', '15', '4', '4');

2.2 准备前端页面

在项目中对应的 HTML 页面中,先新建一个 div,用来显示柱状图,简单设置一下样式,代码如下:

<div class="chart_div">
  <div id = "dataByYear" style="width:500px;height: 300px"> </div>
  <div class="chart_title">2021年-2023年考研参考学员数据对比</div>
</div>

这段代码中,id 为 dataByYear 的 div 是待会儿我们用来显示图表的 div。

2.3 从官网案例中复制代码

读者可以从官网案例地址中找到自己想要的图表样式,比如:柱状图、折线图等等,这里我使用如下的图表样式:

点击进去,选择到 js 代码,将其中的 option 代码复制出来,粘贴到项目代码中,如下图所示:

从效果图和代码图的对比,我们很容易发现里面需要需改的地方,首先图表的横向代码为:

也就是说,如果我们需要修改水平方向上显示的内容,可以更这个 xAxis 中的 data 数组。在本案例中,我们横向显示的是考研数据设计到的年份,而这个年份,我们需要根据后台数据库中的数据查询,看数据分别涉及的是哪些年份,于是我们首先定义一个数组 xdata,方便后续从后台拿取数据。

var xdata = [];

然后再将上面 xAxis 中的 data 替换成 xdata,如下图所示:

紧接着,我们去修改一下每个柱子的数据,通过对比分析,我们不难发现,案例源代码中的 series:中就是每个柱子对应的数据,如下图所示:

在本案例中,我们分别要显示专业总人数、参考人数、上线人数以及录取人数,而这些数据也是需要从后台的数据库中获取,因此我们和上面一样,先定义对应的数组,用来存放从后台查询出来的对应的数据,如下图所示:

然后,删除series 多余的项,保留四个,分别修改成对应的数据,如下所示:

series: [
  {
    name: '总人数',
    type: 'bar',
    emphasis: {
      focus: 'series'
    },
    data: total_nums
  },
  {
    name: '参考人数',
    type: 'bar',
    emphasis: {
      focus: 'series'
    },
    data: exam_nums
  },
  {
    name: '上线人数',
    type: 'bar',
    emphasis: {
      focus: 'series'
    },
    data: online_nums
  },
  {
    name: '通过人数',
    type: 'bar',
    emphasis: {
      focus: 'series'
    },
    data: pass_nums
  }
]

接下来,发送异步请求,从后台拿数据,分别设置到几个数组中,代码如下:

$.ajax({
					type: "GET",
					dataType: "json",
					url: "/kyInfo/showDataByYear",
					async: false,
					success: function (obj) {
						data = obj;

						for (var i = 0; i < data.length; i++) {
							xdata.push(data[i].exam_year);
							var exam_map = data[i];
							console.log(data[i]);

							total_nums.push(exam_map.total_num);
							exam_nums.push(exam_map.exam_num);
							online_nums.push(exam_map.online_num);
							pass_nums.push(exam_map.pass_num);
						}
					}
				}
		);

前端完整代码如下:

function showDataByYear(){

		var chartDom = document.getElementById('dataByYear');
		var myChart = echarts.init(chartDom);
		var option;
		var xdata = [];
		var data;

		var total_nums = []; // 专业总人数
		var exam_nums = []; // 参考人数
		var online_nums = []; // 上线人数
		var pass_nums = []; // 录取人数
		$.ajax({
					type: "GET",
					dataType: "json",
					url: "/kyInfo/showDataByYear",
					async: false,
					success: function (obj) {
						data = obj;

						for (var i = 0; i < data.length; i++) {
							xdata.push(data[i].exam_year);
							var exam_map = data[i];
							console.log(data[i]);

							total_nums.push(exam_map.total_num);
							exam_nums.push(exam_map.exam_num);
							online_nums.push(exam_map.online_num);
							pass_nums.push(exam_map.pass_num);
						}
					}
				}
		);
		console.log(total_nums);
		option = {
			tooltip: {
				trigger: 'axis',
				axisPointer: {
					type: 'shadow'
				}
			},
			legend: {},
			grid: {
				left: '3%',
				right: '4%',
				bottom: '3%',
				containLabel: true
			},
			xAxis: [
				{
					type: 'category',
					data: xdata
				}
			],
			yAxis: [
				{
					type: 'value'
				}
			],
			series: [
				{
					name: '总人数',
					type: 'bar',
					emphasis: {
						focus: 'series'
					},
					data: total_nums
				},
				{
					name: '参考人数',
					type: 'bar',
					emphasis: {
						focus: 'series'
					},
					data: exam_nums
				},
				{
					name: '上线人数',
					type: 'bar',
					emphasis: {
						focus: 'series'
					},
					data: online_nums
				},
				{
					name: '通过人数',
					type: 'bar',
					emphasis: {
						focus: 'series'
					},
					data: pass_nums
				}
			]
		};
		myChart.setOption(option);

	}

2.4 SpringBoot 后台查询数据

编写控制器代码,处理前端发送的showDataByYear 请求:

@RequestMapping("/showDataByYear")
@ResponseBody
public List<Map<String,Object>> showDataByYear(){
    List<Map<String,Object>> data = kyInfoService.getDataByYear();
    return data;
}

编写业务层代码,处理具体的业务逻辑


@Override
public List<Map<String, Object>> getDataByYear() {
    QueryWrapper<ExamStat> lqw = new QueryWrapper<ExamStat>();
    lqw.select("exam_year," +
               "sum(total_num) as total_num," +
               "sum(exam_num) as exam_num," +
               "sum(online_num) as online_num," +
               "sum(pass_num) as pass_num ");
    lqw.groupBy("exam_year");
    List<Map<String, Object>> statList = examStatMapper.selectMaps(lqw);
    System.out.println(statList);
    return statList;
}

本案例中使用的是 mybatis-plus,读者也可以使用 mybatis 或者其他的技术实现。

部署项目,启动测试,效果如图所示:

三、SpringBoot+vue3.0+Echarts

实际上 vue 的实现方式和 一般的 html 页面实现方式大同小异,仅仅是前端发送请求的时候有所差异,其他 echarts 相关的显示部分,和前面案例是一样的,Vue 发送请求代码如下:

 await axios.post(
        "/api/sysUser/showDataByYear",
        
        ).then(res=>{
            const data = res.data
            console.log(data);
            for (var i = 0; i < data.length; i++) {
				xdata.push(data[i].exam_year);
				var exam_map = data[i];
				console.log(data[i]);

				total_nums.push(exam_map.total_num);
				exam_nums.push(exam_map.exam_num);
				online_nums.push(exam_map.online_num);
				pass_nums.push(exam_map.pass_num);
			}
 });

注意,这里我们需要使用 await 实现同步请求,等待后端响应数据之后再渲染图表,否则如果渲染完毕图表此时后端数据还没返回,此时就会看到空的图表。

前端发送请求完整代码如下:

<script setup>
    import {reactive,ref,onMounted} from 'vue';
    import * as echarts from "echarts";
    // import { formInstance } from 'element-plus';
    import axios from 'axios';
    import qs from 'querystring'
     // js中获取状态管理中存的值
    import { useStore } from 'vuex';
    import { useRouter } from 'vue-router';

    const router = useRouter();

    const store = useStore();

    onMounted(()=>{
        showDataByYear();
    });


    const showDataByYear = async ()=>{
        var chartDom = document.getElementById('dataByYear');
		var myChart = echarts.init(chartDom);
		var option;
		var xdata = [];
		var data = {};

		var total_nums = [];
		var exam_nums = [];
		var online_nums = [];
		var pass_nums = [];

        // var res = await axios.get("/api/sysUser/showDataByYear");
        // data = res.data;
     await axios.post(
        "/api/sysUser/showDataByYear",
        
        ).then(res=>{
            const data = res.data
            console.log(data);
            for (var i = 0; i < data.length; i++) {
				xdata.push(data[i].exam_year);
				var exam_map = data[i];
				console.log(data[i]);

				total_nums.push(exam_map.total_num);
				exam_nums.push(exam_map.exam_num);
				online_nums.push(exam_map.online_num);
				pass_nums.push(exam_map.pass_num);
			}
        });
		
		console.log(total_nums);
		option = {
			tooltip: {
				trigger: 'axis',
				axisPointer: {
					type: 'shadow'
				}
			},
			legend: {},
			grid: {
				left: '3%',
				right: '4%',
				bottom: '3%',
				containLabel: true
			},
			xAxis: [
				{
					type: 'category',
					data: xdata
				}
			],
			yAxis: [
				{
					type: 'value'
				}
			],
			series: [
				{
					name: '总人数',
					type: 'bar',
					emphasis: {
						focus: 'series'
					},
					data: total_nums
				},
				{
					name: '参考人数',
					type: 'bar',
					emphasis: {
						focus: 'series'
					},
					data: exam_nums
				},
				{
					name: '上线人数',
					type: 'bar',
					emphasis: {
						focus: 'series'
					},
					data: online_nums
				},
				{
					name: '通过人数',
					type: 'bar',
					emphasis: {
						focus: 'series'
					},
					data: pass_nums
				}
			]
		};
		myChart.setOption(option);

    }
  }

如有疑问,可宫粽好,墨轩学习网,一起交流,感谢阅读

给个不要钱的三连吧:关注+点赞+收藏  O(∩_∩)O哈哈~

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐