Echarts图表
1, Echarts是图表组件
官网: https://echarts.apache.org
2, 入门
2.1, 引入js包
<script src="js/echarts.min.js"></script>
2.2, 准备一个有宽和高的div, 记得设置一个id值
<body>
<div id="main" style="width: 1400px;height:400px;"></div>
</body>
2.3, 初始化echarts
var myChart = echarts.init(document.getElementById('main'));
2.4, 到官方示例里复制一个option, 并调用echarts实例的setOption()方法,显示图表
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar'
}
]
};
2.5, 配置数据并显示图表
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
结果如下图:
3, 修改data属性, 显示不同柱状图和数据
option = {
xAxis: {
type: 'category',
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
},
yAxis: {
type: 'value'
},
series: [
{
data: [-20, -25, -15, -8, 10, 20, 26, 35, 30, 20, 10, -10],
type: 'bar',
label: {
show: true
}
}
]
};
4, 显示标签文字label
图表上的文字叫标签
option = {
xAxis: {
type: 'category',
data: ['语文', '数学', '英语', '物理', '化学', '生物', '体育']
},
yAxis: {
type: 'value'
},
series: [
{
name: '降雨量',
data: [90, 110, 130, 40, 100, 89, 76],
type: 'bar',
label: {
show: true
}
}
]
};
6,显示标题title
下面的代码中left表示位置,有3种写法
left=‘left’ 表示左侧 (left: 左侧, center:中间, right: 右侧)
left=‘30’ 表示距离左侧30像素
left=‘5-%’ 表示距离左侧50%
option = {
title: {
text: '全年温度变化',
left: 'center'
},
xAxis: {
type: 'category',
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
},
yAxis: {
type: 'value'
},
series: [
{
data: [-20, -25, -15, -8, 10, 20, 26, 35, 30, 20, 10, -10],
type: 'bar',
label: {
show: true
}
}
]
};
7,提示工具tooltip
option = {
xAxis: {
type: 'category',
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
},
yAxis: {
type: 'value'
},
tooltip: {
formatter: '{b} {c}°'
},
series: [
{
data: [-20, -25, -15, -8, 10, 20, 26, 35, 30, 20, 10, -10],
type: 'bar',
label: {
show: true
}
}
]
};
8,横向纵向切换
xAxis: 表示横轴 yAxis: 表示纵轴
category: 表示类目型, value: 表示数值型
将xAxis和yAxis互换位置即可达到横纵切换
option = {
title: {
text: '全年温度变化',
left: 'center'
},
yAxis: {
type: 'category',
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
},
xAxis: {
type: 'value'
},
series: [
{
data: [-20, -25, -15, -8, 10, 20, 26, 35, 30, 20, 10, -10],
type: 'bar',
label: {
show: true
}
}
]
};
9, 显示双图表series
series(系列)是一个数组, 每一个元素都是一个图表
option = {
xAxis: {
type: 'category',
data: ['一季度', '二季度', '三季度', '四季度']
},
yAxis: {
type: 'value'
},
series: [
{
name: '降雨量',
data: [100, 200, 150, 50],
type: 'bar'
},
{
name: '蒸发量',
data: [20, 50, 120, 10],
type: 'bar'
}
]
};
10, 双图表切换legend
必须给图表系列设置name属性
option = {
legend:{},
xAxis: {
type: 'category',
data: ['一季度', '二季度', '三季度', '四季度']
},
yAxis: {
type: 'value'
},
series: [
{
name: '降雨量',
data: [100, 200, 150, 50],
type: 'bar'
},
{
name: '蒸发量',
data: [20, 50, 120, 10],
type: 'bar'
}
]
};
11, 横轴标签显示全部文字并旋转角度
option = {
grid: {
bottom: 90
},
xAxis: {
type: 'category',
data: ['张飞', '关羽', '刘备', '诸葛亮', '孙权', '赵云', '周瑜', '黄忠', '魏延', '马谡', '张角', '孙尚香', '曹操', '关平', '司马懿'],
axisLabel: {
//显示全部标签
interval: 0,
//旋转45度
rotate: 45
}
},
yAxis: {
type: 'value'
},
tooltip: {
formatter: '{b} {c}°'
},
series: [
{
data: [100,99,98,50,60,70,80,90,100,88,66,45,32, 88,99],
type: 'bar',
label: {
show: true
}
}
]
};
12, 双纵轴yAxis
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: [
{
type: 'value'
},
{
type: 'value',
position: 'right',
alignTicks: true,
}
],
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
},
{
data: [120, 210, 214, 118, 235, 247, 160],
type: 'line',
yAxisIndex: 1 //使用索引为1的纵轴
}
]
};
13, 显示饼图百分比数
用formatter自定义显示格式
option = {
title: {
text: '各年龄人数',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [
{
name: '人数',
type: 'pie',
radius: '50%',
label: {
formatter: '{b} {d}%'
},
data: [
{ value: 1048, name: '0-14岁' },
{ value: 735, name: '15-24岁' },
{ value: 580, name: '25-40岁' },
{ value: 484, name: '41-65岁' },
{ value: 300, name: '66-100岁' }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
14, 显示工具箱toolbox
toolbox: {
show: true,
feature: {
dataZoom: {
yAxisIndex: 'none'
},
dataView: { readOnly: false },
magicType: { type: ['line', 'bar'] },
restore: {},
saveAsImage: {}
}
}
15, 显示标注与标线
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar',
markPoint: {
data: [
{ type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' }
]
},
markLine: {
data: [{ type: 'average', name: 'Avg' }]
}
}
]
};
16, 实战1-查询每年|月旅游人数
(1),先编写SQL语句
-- 查询每年旅游人数
select year(t.tour_date) date,count(*) count
from tour t
group by year(t.tour_date)
order by date
-- 查询指定年,例如2021 每月旅游人数
select month(t.tour_date) date,count(*) count
from tour t
where year(t.tour_date) = 2021
group by month(t.tour_date)
order by date
(2), 在echarts官网里设计一个静态页面
option = {
title: {
text: '每年/月旅游人数'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'value',
boundaryGap: [0, 0.01]
},
yAxis: {
type: 'category',
data: ['2017', '2018', '2019', '2020', '2021', '2022']
},
series: [
{
name: '2011',
type: 'bar',
data: [18203, 23489, 29034, 4970, 31744, 30230]
}
]
};
(3), 在项目的页面里显示这个柱状图
//初始化图表
var myChart = echarts.init(document.getElementById('main'));
//将上面的option复制到个位置
//配置图表
myChart.setOption(option);
(4), 写一个query方法, 编写ajax查询数据
function query1(){
var year = $("#date1").val();
$.ajax({
type: "get",
url: "/tour/statisticsYearOrMonth",
data: {"year": year},
dataType: "json",
async: true,
cache: false,
beforeSend: function(){layer.load();},
success: function(result){
},
error: function(){layer.alert("请求失败");},
complete: function(){layer.closeAll("loading");}
});
}
//调用一次
query1();
(5), 做一个封装类, 封装年或者月和旅游人数的类
@Data
public class TourCount {
private String date;
private Long count;
}
(6), 编写controller代码
@GetMapping("/tour/statisticsYearOrMonth")
@ResponseBody
public Map<String, Object> statisticsYearOrMonth(String year){
List<TourCount> list = null;
//如果有年,则查询月份旅游人数
if (year != null && !"".equals(year)) {
List<TourCount> lsList = tourService.queryStatisticsMonth(year);
//给月份后面添加'月'这个字
list = lsList.stream().peek(p->p.setDate(p.getDate()+"月")).collect(Collectors.toList());
} else {
//如果没有年,则查询每年旅游人数
list = tourService.queryStatisticsYear();
}
//从list里分别获取date和count装到两个独立的list里
List<String> dateList = new ArrayList<>();
List<Long> countList = new ArrayList<>();
for (TourCount t : list) {
dateList.add(t.getDate());
countList.add(t.getCount());
}
//将两个list封装到map里,传给页面
Map<String, Object> map = new HashMap<>();
map.put("dateList", dateList);
map.put("countList", countList);
return map;
}
(7), 完善页面js代码
//将静态数据改为动态显示
function query1(){
var year = $("#date1").val();
$.ajax({
type: "get",
url: "/tour/statisticsYearOrMonth",
data: {"year":year},
dataType: "json",
async: true,
cache: false,
beforeSend: function(){layer.load();},
success: function(result){
option.yAxis.data=result.dateList;
option.series[0].data = result.countList;
//根据option生成图表
myChart.setOption(option);
},
error: function(){layer.alert("请求失败");},
complete: function(){layer.closeAll("loading");}
});
}
//页面加载后先运行一次
query1();
结果
和
17, 实战2-每年|月男女旅游人数对比
(1), 先编写SQL语句
-- 每年 男 女 旅游人数
select year(t.tour_date) as date,
count(case when t.sex=1 then '男' end) as mancount,
count(case when t.sex=0 then '女' end) as womencount
from tour t
group by year(t.tour_date)
order by date
-- 指定年, 每月 男 女 旅游人数
select month(t.tour_date) as date,
count(case when t.sex=1 then '男' end) as mancount,
count(case when t.sex=0 then '女' end) as womencount
from tour t
where year(t.tour_date)='2021'
group by month(t.tour_date)
order by date
(2), 设计静态页面
option = {
title: {
text: '查询每年|月男女旅游人数对比'
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: [
{
name: '男',
type: 'value',
axisLine: {show: true}
},
{
name: '女',
type: 'value',
alignTicks: true,
axisLine: {show: true}
}
],
legend: {},
series: [
{
name: '男',
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
smooth: true,
label: {show: true}
},
{
name: '女',
data: [220, 332, 401, 534, 790, 830, 1920],
type: 'line',
smooth: true,
yAxisIndex: 1,
label: {show: true}
}
]
};
(3), 封装一个新的类来接值
@Data
public class TourSexCount {
/**
* 年 或者 月
*/
private String date;
/**
* 男 旅游人数
*/
private Long mancount;
/**
* 女 旅游人数
*/
private Long womencount;
}
(4), controller和service写法
@GetMapping("/tour/statisticsManOrWoman")
@ResponseBody
public Map<String, Object> statisticsManOrWoman(String year){
List<TourSexCount> list = null;
if (year != null && !"".equals(year)) {
List<TourSexCount> list2 = tourService.queryStatisticsManOrWomanOfMonth(year);
list = list2.stream().peek(t -> t.setDate(t.getDate()+"月")).collect(Collectors.toList());
} else {
list = tourService.queryStatisticsManOrWoman();
}
//封装页面需要的数据结构
List<String> dateList = new ArrayList<>();
List<Long> manList = new ArrayList<>();
List<Long> womanList = new ArrayList<>();
for (TourSexCount t : list) {
dateList.add(t.getDate());
manList.add(t.getMancount());
womanList.add(t.getWomencount());
}
//将3个list封装到map里,传给页面
Map<String, Object> map = new HashMap<>();
map.put("dateList", dateList);
map.put("manList", manList);
map.put("womanList", womanList);
return map;
}
(4), 页面js写法
function query2(){
var year = $("#date2").val();
$.ajax({
type: "get",
url: "/tour/statisticsManOrWoman",
data: {"year": year},
dataType: "json",
async: true,
cache: false,
beforeSend: function(){layer.load();},
success: function(result){
option.xAxis.data=result.dateList;
option.series[0].data = result.manList;
option.series[1].data = result.womanList;
myChart.setOption(option);
},
error: function(){layer.alert("请求失败");},
complete: function(){layer.closeAll("loading");}
});
}
query2();
结果
和
18, 实战3-查询各年龄段旅游人数
(1), sql语句
-- 各年龄段旅游人数
select
count(case when age <24 then 1 end) a,
count(case when age >=24 and age <= 30 then 1 end) b,
count(case when age >=31 and age <= 37 then 1 end) c,
count(case when age >=38 and age <= 55 then 1 end) d,
count(case when age >=56 and age <= 65 then 1 end) e,
count(case when age >=66 then 1 end) f
from tour
(2),设计静态页面
option = {
title: {
text: '各年龄段旅游人数',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [
{
name: 'Access From',
type: 'pie',
radius: '50%',
label: {
formatter: '{b} {d}%'
},
data: [
{ value: 1048, name: '23岁以内' },
{ value: 735, name: '24-30岁' },
{ value: 580, name: '31-37岁' },
{ value: 484, name: '38-55岁' },
{ value: 300, name: '56-65岁' },
{ value: 300, name: '66岁' }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
(3), 控制层代码
@GetMapping("/tour/statisticsAge")
@ResponseBody
public List<Map<String, Object>> statisticsAge(){
//查询各个年龄段人数
Map<String,Long> countMap = tourService.statisticsAge();
List<Map<String, Object>> list = new ArrayList<>();
Map<String, Object> mapa = new HashMap<>();
Map<String, Object> mapb = new HashMap<>();
Map<String, Object> mapc = new HashMap<>();
Map<String, Object> mapd = new HashMap<>();
Map<String, Object> mape = new HashMap<>();
Map<String, Object> mapf = new HashMap<>();
mapa.put("value", countMap.get("a"));
mapa.put("name", "24岁以下");
mapb.put("value", countMap.get("b"));
mapb.put("name", "24-30岁");
mapc.put("value", countMap.get("c"));
mapc.put("name", "31-37岁");
mapd.put("value", countMap.get("d"));
mapd.put("name", "38-55岁");
mape.put("value", countMap.get("e"));
mape.put("name", "56-65岁");
mapf.put("value", countMap.get("f"));
mapf.put("name", "66岁以上");
list.add(mapa);
list.add(mapb);
list.add(mapc);
list.add(mapd);
list.add(mape);
list.add(mapf);
return list;
}
(4), 页面代码
function query(){
$.ajax({
type: "get",
url: "/tour/queryAgeGroup",
data: {},
dataType: "json",
async: true,
cache: false,
beforeSend: function(){layer.load();},
success: function(result){
option.series[0].data = result;
myChart.setOption(option);
},
error: function(){layer.alert("请求失败");},
complete: function(){layer.closeAll("loading");}
});
}
query();
结果