一、前置工作
通过npm引入echarts等就不在介绍,echarts官网地址echarts官网,可以从中挑选喜欢的组件自行修改。
界面图形效果如下:
二、前端
在页面首先定义一个容器,用于存放图形展示的位置。前后端交互主要思路(以折柱结合图为例):
在页面定义好echarts后,我们需要做的主要就是从后端拿去X、Y轴数据来填充。这里需要注意X轴一般是固定的值。而Y轴的值则是与X轴对应的number值。如果你想展示一个种数据,那么后端返回一个Y轴数据,如果想展示两种数据,那么后端需要返回两个Y轴数据。以此类推。将数据填充好后剩下的就是echarts组件的一些功能按需引入,代码中有一些关键点注释,大家可以直接参考,echarts封装的组件还是非常强大的,若有一些特殊需求,请参考官网文档。此为一个完整页面,可以直接运行,若仅仅需要展示图像,那么请只关注这部分相关的逻辑。
<template>
<div style="margin-left:15px;">
<h2>系统公告</h2>
<el-row style="margin-top: 15px;">
<el-col :span="12">
<el-collapse v-model="activeName" accordion>
<el-collapse-item
v-for="item in noticeData"
:key="item.id"
:title="item.name"
:name="item.id"
>
<div style="padding:0 20px;">
<strong>公告内容:</strong>
{{ item.content }}
</div>
<div style="padding:0 20px;">
<strong>发布时间:</strong>
{{ item.pubDate }}
</div>
</el-collapse-item>
</el-collapse>
</el-col>
<el-col :span="4" class="statisticStyle">
<el-statistic title="展示数据1" :value="268500" />
</el-col>
<el-col :span="4" class="statisticStyle">
<el-statistic title="展示数据2" :value="outputValue" />
</el-col>
<el-col :span="4" class="statisticStyle">
<el-statistic title="展示数据3" :value="123213" />
</el-col>
</el-row>
<el-row style="margin-top: 45px;">
<el-col :span="12" class="statisticStyle">
<div ref="echartsRef" style="height: 400px; width: 500px">gamePlay</div>
</el-col>
<el-col :span="12" class="statisticStyle">
<div ref="echartsPie" style="height: 400px; width: 500px">echartsPie</div>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { useTransition } from "@vueuse/core";
import * as echarts from "echarts";
import { getData, getData2 } from "@/api/test/newindex";
const echartsRef = ref();
const echartsPie = ref();
const echartsLine = ref();
const noticeData = [
{ id: 1, name: "公告标题1", content: "公告内容1", pubDate: "2024-04-11" },
{ id: 2, name: "公告标题2", content: "公告内容2", pubDate: "2024-04-11" },
{ id: 3, name: "公告标题3", content: "公告内容3", pubDate: "2024-04-11" },
{ id: 4, name: "公告标题4", content: "公告内容4", pubDate: "2024-04-11" },
{ id: 5, name: "公告标题5", content: "公告内容5", pubDate: "2024-04-11" },
];
const activeName = ref(noticeData.length > 0 ? noticeData[0].id : "");
onMounted(() => {
initBar();
});
const source = ref(0);
const outputValue = useTransition(source, {
duration: 1500
});
source.value = 172000;
function initBar() {
getData().then(res => {
if (res.code == 200 && res.data != null) {
getBar(res.data.xAxis, res.data.yAxis, res.data.yAxis2);
}
});
getData2().then(res => {
if (res.code == 200 && res.data != null) {
getPie(res.data);
}
});
}
function getBar(xAxis, yAxis, yAxis2) {
const myChart = echarts.init(echartsRef.value);
// 指定图表的配置项和数据
const option = {
title: {
text: "柱状图示例"
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
crossStyle: {
color: "#999"
}
}
},
//右上角操作区
toolbox: {
feature: {
dataView: { show: true, readOnly: false },
magicType: { show: true, type: ["line", "bar"] },
restore: { show: true },
saveAsImage: { show: true }
}
},
//图例
legend: {
data: ["错误数量", "占比"]
},
xAxis: {
data: xAxis
},
yAxis: [
{
type: "value",
name: "错误数量",
show: true,
interval: 10,
axisLine: {
lineStyle: {
color: "#5e859e",
width: 2
}
}
},
{
type: "value",
name: "占比",
min: 0,
max: 100,
interval: 10,
axisLabel: {
formatter: "{value} %"
},
axisLine: {
lineStyle: {
color: "#5e859e", //纵坐标轴和字体颜色
width: 2
}
}
}
],
series: [
{
name: "错误数量",
type: "bar",
data: yAxis
},
{
name: "占比",
type: "line",
smooth: true,
yAxisIndex: 1, //索引从0开始
data: yAxis2,
tooltip: {
valueFormatter: function(value) {
return value + " %";
}
}
}
]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
}
function getLine(xAxis, yAxis) {
const myChartLine = echarts.init(echartsLine.value);
// 指定图表的配置项和数据
const option = {
title: {
text: "折线图示例"
},
tooltip: {},
legend: {
data: [
{
name: "错误数量",
// 强制设置图形为圆。
icon: "circle",
// 设置文本为红色
textStyle: {
color: "black"
}
}
]
},
xAxis: {
data: xAxis
},
yAxis: {},
series: [
{
name: "错误数量",
type: "line",
data: yAxis
}
]
};
// 使用刚指定的配置项和数据显示图表。
myChartLine.setOption(option);
}
function getPie(data) {
const myChartPie = echarts.init(echartsPie.value);
const option = {
title: {
text: "饼状图示例"
},
tooltip: {
trigger: "item"
},
// //右上角操作区
// toolbox: {
// feature: {
// dataView: { show: true, readOnly: false },
// restore: { show: true },
// saveAsImage: { show: true }
// }
// },
radius: ["40%", "70%"],
legend: {
top: "5%",
left: "center"
},
series: [
{
name: "访问来源",
type: "pie", // 设置图表类型为饼图
radius: ["40%", "70%"], // 饼图的半径,外半径为可视区尺寸(容器高宽中较小一项)的 55% 长度。
itemStyle: {
borderRadius: 10,
borderColor: "#fff",
borderWidth: 2
},
toolyip: {
trigger: "item",
formatter: "{b}:{c}({d}%)"
},
label: {
show: false,
position: "center"
},
//中间框字体样式
emphasis: {
label: {
show: true,
fontSize: 30,
fontWeight: "bold"
}
},
labelLine: {
show: false
},
data
}
]
};
myChartPie.setOption(option);
}
</script>
<style scoped>
.el-statistic {
--el-statistic-content-font-size: 38px;
--el-statistic-title-font-size: 18px;
}
.el-collapse-item{
--el-collapse-header-font-size: 16px;
}
::v-deep .el-collapse-item__header{
font-weight: 550;
}
.statisticStyle {
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex-wrap: nowrap; /* 防止子元素换行 */
}
</style>>
三、后端
此处仅仅演示了前后端交互效果,并没有具体业务逻辑,大家可以根据自己业务逻辑来实现。
@RestController
@RequestMapping("/echartsData")
public class EchartsDataController {
@GetMapping("/echarts/chartOne")
public AjaxResult chartOne(){
//返回前端的数据
List<Map<String,Object>> mapList = new ArrayList<>();
//循环
List<String> xAxis = new ArrayList<>();
List<Integer> yAxis = new ArrayList<>();
List<Integer> yAxis2 = new ArrayList<>();
String[] clothes = {"数字", "宽带", "OTT", "移网", "固话", "集团"};
xAxis.addAll(Arrays.asList(clothes));
int[] number = {5, 20, 36, 10, 10, 20};
for (int num : number) {
yAxis.add(num);
}
int[] number2 = {5, 30, 66, 10, 20, 80};
for (int num : number2) {
yAxis2.add(num);
}
Map<String,Object> map = new HashMap<>();
map.put("xAxis",xAxis);
map.put("yAxis",yAxis);
map.put("yAxis2",yAxis2);
return AjaxResult.success(map);
}
@GetMapping("/echarts/chartTwo")
public AjaxResult chartTwo(){
//返回前端的数据
List<PieDto> list = new ArrayList<>();
list.add(new PieDto("视频广告",235));
list.add(new PieDto("邮件营销",610));
list.add(new PieDto("直接访问",335));
list.add(new PieDto("搜索引擎",600));
list.add(new PieDto("小程序跳转",835));
return AjaxResult.success(list);
}
dto如下
@Data
@AllArgsConstructor
public class TestDto {
private String name;
private int number;
private String type;
}
@Data
@AllArgsConstructor
public class PieDto {
private String name;
private int value;
}