是什么?
百度开发的基于js的开源可视化库,提供丰富的图表组件
图表包括 折线图,柱状图,饼图,散点,圆环,雷达图等
有什么用?
将冷冰冰的数据以图表的形式更加直观明了的展现给用户,用户数据分析,统计等
快速入门
1-安装
从npm安装
npm install echarts
从cdn获取
https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js
2-项目引入
在使用该库的页面导入,或者在main.js里全局引入
import * as echarts from 'echarts';
3-实例/初始化echarts
//准备dom,指定好宽高
<div id="main" style="width: 600px;height:400px "></div>
//mounted里初始化(当dom加载完执行的钩子函数)
mounted() {
//获取目标dom并进行初始化
const myChart = echarts.init(document.getElementById('main'));
}
4-补充图表属性(基础的柱状图)
const option={
xAxis:{
data:['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis:{
},
series: [
{
type: 'bar',
data: [23, 24, 18, 25, 27, 28, 25]
}
]
}
xAixs横坐标对象
属性值
- data数组:表示x轴的每个刻度值
yAxix纵坐标对象
一般不设数据,以确定的数据来自适应范围
series系列数组/单个对象
可以表示数据在不同时间的值,可以有多个,例如2017,2018,2019年的数据统计,通俗点来讲,就是将多张图柔和成一张
属性值
- type:图的类型,bar为柱状,line为线性,pie也就是Π,顾名思义就为圆型图,应外观像饼也称之为饼状图
- data数组:每个x刻度对应的Y值,例如,X为星期一,对应的第一个值为32,也就是说在星期一卖出了32个数量的物品
5-设置图表属性
myChart.setOption(option)
完成上述5步后可以发现div被渲染为如下图
如果想要与真实数据绑定只需要将
具体属性
x/yAsix
-
type:(默认category)
category-离散的,x轴刻度与刻度之间没有数据,不连续的,刻度唯一性,例如星期一到星期日,一般用于柱状图,一个X刻度对应一个Y
value-x轴刻度与刻度之间可以有多个Y值,连续的,一般与精确的折线图,刻度间可以有数据
图解
-
data数组:x轴刻度值
-
axisLine 轴线对象
axisLine: { //轴线特征,arrow为两端带箭头 symbol: 'arrow', //轴线样式,dashed虚线,默认为solid实线 lineStyle: { type: 'dashed' } }
-
axisTick 刻度线对象
axisTick: { //和标签对齐 alignWithLabel: true, //刻度线长度 length: 6, lineStyle: { //线的类型 type: 'dashed' // ... } },
-
axisLabel 刻度标签
axisLabel: { //给X轴的data设置一个kg单位 formatter: '{value} kg', //与刻度对齐 align: 'center' // ... },
-
splitLine 每个刻度分隔图表的线
splitLine: { show: true },
-
name 显示在最上面/最右边的名字
-
min/max(配合value类型)
-
position:轴线位置
series
-
type:图表类型
‘bar’:柱状图
‘line’:折线图
‘pie’:饼图 -
data: 该对象的具体数据
-
label: 分类的标签显示
//在原先标签也就是param.name的基础上 加(param.percent%)百分比提示,由变量+字符串组合而成的label formatter(param){ return param.name+'(' +param.percent +'%)' }
-
x/yAxisIndex: 指定使用的轴线
-
smooth:线状图的弧度。只在line类型有效
-
itemStyle:图形样式
//柱状图的圆角度 barBorderRadius: 10, //边框宽度 borderWidth: 8, //边框类型 borderType: 'dashed', //边框颜色 borderColor: '#73c0de', //阴影颜色 shadowColor: '#ff6a6a', //阴影X偏移 shadowOffsetX: 2, //阴影模糊 shadowBlur: 3
-
柱子样式
//柱宽 barWidth: '20%' //同类柱间距 barGap:"1%" //不同类间距 barCategoryGap: '80%' //柱条背景色 showBackground: true,/ backgroundStyle: { color: 'rgba(220, 220, 220, 0.8)' // }
legend
-
type:图例类型 (‘sroll’)当图例类型过多的时候,滚动显示
-
show:展示状态 (true/false),不知道设来干嘛的,既然我都设置legend属性了,还设false,不是脱裤子放屁吗
-
selected:默认展示的图例类型
selected: { '2015': true, '2016': true, '2017': false },
-
textStyle:图例文字样式
textStyle: { color: '#ccc' // ... },
-
backgroundColor:‘#ccc’
当图表背景色为深黑色时可以开启,突出图例颜色
-
orient 朝向,排列
‘horizontal/vertical’
-
right/left/top/bottom 往这个边缘远离多少距离
right:3 意思为离右边缘有3距离 -
top/left 图例位置
center 上边/左边中间(只有top能设。目前不清楚为什么)
grid
//图表
grid: {
//与容器左侧的距离,越大X轴越紧凑
left: 10,
//图表自适应容器,防止图表超出容器从而坐标轴显示不全问题
containLabel: false,
//与容器底,顶,左,右部的距离,越大图表越紧凑
bottom: 10,
top: 70,
right: 40
},
tooltip
tooltip: {
//触发提示条,当鼠标悬停在坐标轴上则提示,
// 另一个参数为item,当鼠标悬停在柱状图上显示
trigger: 'axis',
//提示框数值格式化,就是在当前y值后面加单位
//局部添加则在series里增加tooltip{valueFormatter...}
valueFormatter: value => value + 'kg',
//坐标轴指示器,提示当前鼠标悬浮位置的X,Y值
//当 type 属性设置为 'cross' 时,坐标轴指示器会显示一条垂直于横轴和一条水平于纵轴的线,形成一个十字准星的形状。
axisPointer: {type: 'cross'}
},
backgroundColor
backgroundColor: {
//径向渐变。有半径的渐变 ,也就是圆渐变
//可定义起始位置和半径,
// 这里的半径是容器的宽高百分比 0.8意味着半径是容器宽高的百分之80%
type: 'radial',
x: 0.3,
y: 0.3,
r: 0.8,
//颜色点,用于定义从一个点到另一个点的偏移过程
//从百分之0 offset的浅灰色,逐渐变成 百分之100 offset的深灰色,越靠近100越深灰色
//中间可以有多个渐变色
colorStops: [
{
offset: 0,
color: '#f7f8fa'
},
{
offset: 1,
color: '#cdd0d5'
}
]
},
emphasis
emphasis: {
itemStyle: {
// 高亮时点的颜色。
color: 'skyblue'
},
label: {
show: true,
// 高亮时显示的文字。
// formatter: 'This is a emphasis label.'
}
},
title
//图表标题,默认左上角放置
title: {
text: 'ECharts '
},
visualMap
visualMap: [
//以不同的色块颜色区分数据数量,连续的一条,
// 颜色深度会连续变化,深浅之分
// // 可以同时定义多个 visualMap 组件。
{
// 第一个 visualMap 组件
type: 'continuous'
// 定义为连续型程度渐变 visualMap
// ...
},
// 以不同的色块颜色区分数据数量,分段意思是一块一块的色块
//每个数据范围内固定一种颜色,不会有连续的数据不同而导致深浅之分,简单点就说说没有渐变效果
// {
// // 第二个 visualMap 组件
// type: 'piecewise' // 定义为分段型 visualMap
// // ...
// }
],
图解
continuous
piecewise
dataset
dataset: {
// 提供一份数据。
source: [
['product', '2015', '2016', '2017'],
['Matcha Latte', 43.3, 85.8, 93.7],
['Milk Tea', 83.1, 73.4, 55.1],
['Cheese Cocoa', 86.4, 65.2, 82.5],
['Walnut Brownie', 72.4, 53.9, 39.1]
]
},
//声明X轴,类型为category,类别对应dataset的第一列
xAxis: { type: 'category' },
//Y轴
yAxis: {},
//声明多个Bar,每个bar对应dataset的每一列
series: [{ type: 'bar' }, { type: 'bar' }, { type: 'bar' }]
折线图
只需要将series里的type改成line即可
饼图
option = {
series: [
{
type: 'pie',
data: [
{
value: 335,
name: '直接访问'
},
{
value: 234,
name: '联盟广告'
},
{
value: 1548,
name: '搜索引擎'
}
],
radius: ['40%', '70%']
}
]
};
圆环图
饼图的特例,也就是有内半径的饼图,多了一条配置如下 radius: [‘40%’, ‘70%’],内半径需小于外半径
option = {
series: [
{
type: 'pie',
data: [
{
value: 335,
name: '直接访问'
},
{
value: 234,
name: '联盟广告'
},
{
value: 1548,
name: '搜索引擎'
}
],
radius: ['40%', '70%']
}
]
};
配合emphasis实现悬浮鼠标 中间文字显示
//先隐藏label,位置在中
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '30',
fontWeight: 'bold'
}
},
触发事件
//点击里面的柱状图触发事件,输出柱状图类别
myChart3.on('click', function (params) {
// console.log(params.name);
// window.open("https://www.baidu.com/s?wd="+params.name)
});
param的属性
type EventParams = {
// 当前点击的图形元素所属的组件名称,
// 其值如 'series'、'markLine'、'markPoint'、'timeLine' 等。
componentType: string;
// 系列类型。值可能为:'line'、'bar'、'pie' 等。当 componentType 为 'series' 时有意义。
seriesType: string;
// 系列在传入的 option.series 中的 index。当 componentType 为 'series' 时有意义。
seriesIndex: number;
// 系列名称。当 componentType 为 'series' 时有意义。
seriesName: string;
// 数据名,类目名
name: string;
// 数据在传入的 data 数组中的 index
dataIndex: number;
// 传入的原始数据项
data: Object;
// sankey、graph 等图表同时含有 nodeData 和 edgeData 两种 data,
// dataType 的值会是 'node' 或者 'edge',表示当前点击在 node 还是 edge 上。
// 其他大部分图表中只有一种 data,dataType 无意义。
dataType: string;
// 传入的数据值
value: number | Array;
// 数据图形的颜色。当 componentType 为 'series' 时有意义。
color: string;
};
- 除了click事件还有
//ECharts 支持常规的鼠标事件类型,包括 'click'、 'dblclick'、
// 'mousedown'、 'mousemove'、 'mouseup'、 'mouseover'
// 、 'mouseout'、 'globalout'、 'contextmenu' 事件
后端调用例子
1-接口
@GetMapping("/statistic")
public Result statistic (){
List<Orders> list = ordersService.list();
//获取所有日期
//获取所有日期属性,这里不能用list,因为set遍历出来的日期是唯一的,而list遍历出来的日期不唯一,日期可能重复,后续如果想要for循环累加金额时会出现日期重复
Set<String> times = list.stream().map(Orders::getTime).collect(Collectors.toSet());
//构建一个用来存放图表数据的list
List<Dict> dicts = new ArrayList<>();
//金额数据累加
for (String time : times) {
//过滤出和当前时间一样的订单,然后二次遍历其里面所有金额属性,最后进行add累加
BigDecimal sum = list.stream().filter(orders -> orders.getTime().equals(time)).map(Orders::getPrice).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
//新建一个map,构建存放数据的单个map
Dict dict = Dict.create();
dict.set("date", time).set("value", sum);
//将这个map,键值对存到最终的list列表
dicts.add(dict);
}
return Result.success(dicts);
}
- 获取数据源,获取所有日期,for循环对数据源使用stream流进行过滤筛选出一样日期的订单信息,使用map遍历出所有价格属性的值,reduce调用进行累加,获取到同一日期下的金额总额,将该条数据存放到总列表里,继续遍历下一个日期进行累加金额
2-前端发请求,接收数据
this.$request.get("/orders/statistic").then(res => {
if (res.code == 200) {
//将分类信息传入x轴
option.xAxis.data = res.data?.line?.map(v => v.date) || []
//将具体数据传入series里的data
option.series[0].data = res.data?.line?.map(v => v.value) || []
myChart.setOption(option)
})