数据可视化, 说白了, 就是把数据以更加直观的方式进行呈现. 那什么方式是更加直观的方式呢? 就是图表。
什么是ECharts?
ECharts(全称“EchoCharts”)是一个开源的、纯JavaScript实现的图表库,由百度前端团队(EFE)以及社区贡献者共同维护和开发。它提供了一整套丰富的图表类型,包括折线图、柱状图、饼图、雷达图、散点图、地图、热力图、箱线图等,用于各种数据可视化需求。
<script src="js/echarts.min.js"></script>
<div id="main" style="width: 600px;height:400px;"></div>
var myChart = echarts.init(document.getElementById('main'))
var option = {
xAxis: {
type: 'category',
data: ['小明', '小红', '小王'] },
yAxis: {
type: 'value'
},
series: [
{
name: '语文',
type: 'bar',
data: [70, 92, 87],
}
]
}
myChart.setOption(option)
一个图表最终呈现什么样子,完全取决于这个配置项.所以对于不同的图表, 除了配置项会发生改变之外,其他的代码都是固定不变的
- xAxis
直角坐标系 中的 x 轴, 如果 type 属性的值为 category ,那么需要配置 data 数据, 代表在 x 轴的呈现
- yAxis
直角坐标系 中的 y 轴, 如果 type 属性配置为 value , 那么无需配置 data , 此时 y 轴会自动去series 下找数据进行图表的绘制
- series
系列列表。每个系列通过 type 决定自己的图表类型, data 来设置每个系列的数据
配置项都是以键值对的形式存在, 并且配置项有很多, ECharts 的学习大多是针对于这些配置项的, 对于配置项的学习, 大家可以不用死记硬背, 需要的时候查一查官方文档即可. 网址:https://echarts.apache.org/zh/option.html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="js/echarts.min.js"></script>
</head>
<body>
<div style="width: 600px;height:400px"></div>
<script>
var mCharts = echarts.init(document.querySelector("div")) var option = {}
mCharts.setOption(option)
</script>
</body>
</html>
此时 option 是一个空空如也的对象
var xDataArr = ['张三', '李四', '王五', '闰土', '小明', '茅台', '二妞', '大强']
var yDataArr = [88, 92, 63, 77, 94, 80, 72, 86]
var option = {
xAxis: {
type: 'category',
data: xDataArr
},
yAxis: {
type: 'value'
},
series: [
{
type: 'bar',
data:yDataArr
}
]
}
注意: 坐标轴 xAxis 或者 yAxis 中的配置, type 的值主要有两种: category 和 value , 如果 type属性的值为 category ,那么需要配置 data 数据, 代表在 x 轴的呈现. 如果 type 属性配置为 value ,那么无需配置 data , 此时 y 轴会自动去 series 下找数据进行图表的绘制
series: [
{
......
markPoint: {
data: [
{
type: 'max', name: '最大值'
},
{
type: 'min', name: '最小值'
}
]
}
}
]
series: [
{
......
markLine: {
data: [
{
type: 'average', name: '平均值'
}
]
}
}
]
series: [
{
......
label: {
show: true, // 是否可见
rotate: 60 // 旋转角度
}
}
]
series: [
{
......
barWidth: '30%' // 柱的宽度
}
]
var option = {
xAxis: {
type: 'value'
},
yAxis: {
type: 'category',
data: xDataArr
},
series: [
{
type: 'bar',
data: yDataArr
}
]
}
柱状图描述的是分类数据,呈现的是每一个分类中『有多少?』, 图表所表达出来的含义在于不同类别数据的排名\对比情况
使用 ECharts 绘制出来的图表, 都天生就自带一些功能, 这些功能是每一个图表都具备的, 我们可以通过配置, 对这些功能进行设置.
var option = {
title: {
text: "成绩", // 标题文字
textStyle: {
color: 'red' // 文字颜色
},
borderWidth: 5, // 标题边框 b
orderColor: 'green', // 标题边框颜色
borderRadius: 5, // 标题边框圆角
left: 20, // 标题的位置
top: 20 // 标题的位置
}
}
提示框: tooltip
tooltip 指的是当鼠标移入到图表或者点击图表时, 展示出的提示框
可选值有item\axis
可选值有 mouseOver\click
var option = {
tooltip: {
trigger: 'item',
triggerOn: 'click',
formatter: '{b}:{c}'
}
}
//这个{b} 和 {c} 所代表的含义不需要去记, 在官方文档中有详细的描述
var option = {
tooltip: {
trigger: 'item',
triggerOn: 'click',
formatter: function (arg) {
return arg.name + ':' + arg.data
}
}
}
工具栏的按钮是配置在 feature 的节点之下
var option = {
toolbox: {
feature: {
saveAsImage: {}, // 将图表保存为图片
dataView: {}, // 是否显示出原始数据
restore: {}, // 还原图表
dataZoom: {}, // 数据缩放
magicType: { // 将图表在不同类型之间切换,图表的转换需要数据的支持
type: ['bar', 'line']
}
}
}
}
var option = {
legend: {
data: ['语文', '数学']
},
xAxis: {
type: 'category',
data: ['张三', '李四', '王五', '闰土', '小明', '茅台', '二妞', '大强']
},
yAxis: {
type: 'value'
},
series: [
{
name: '语文',
type: 'bar',
data: [88, 92, 63, 77, 94, 80, 72, 86]
}, {
name: '数学',
type: 'bar',
data: [93, 60, 61, 82, 95, 70, 71, 86]
}
]
}
DOCTYPE html>
<html lang="en">
<head>
<script src="js/echarts.min.js">script>
head>
<body>
<div style="width: 600px;height:400px">div>
<script>
var mCharts = echarts.init(document.querySelector("div")) var option = {}
mCharts.setOption(option)
script>
body>
html>
此时 option 是一个空空如也的对象
var xDataArr = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
var yDataArr = [3000, 2800, 900, 1000, 800, 700, 1400, 1300, 900, 1000, 800, 600]
var option = {
xAxis: {
type: 'category',
data: xDataArr
},
yAxis: {
type: 'value'
},
series: [
{
type: 'line',
data:yDataArr
}
]
}
var option = {
series: [
{
......
markPoint: {
data: [
{
type: 'max',
name: '最大值'
}, {
type: 'min',
name: '最小值'
}
]
}
}
]
}
var option = {
series: [
{
......
markLine: {
data: [
{
type: 'average',
name: '平均值'
}
]
}
}
]
}
var option = {
series: [
{
......
markArea: {
data: [
[
{
xAxis: '1月'
}, {
xAxis: '2月'
}
],
[
{
xAxis: '7月'
}, {
xAxis: '8月'
}
]
]
}
}
]
}
var option = {
series: [
{
......
smooth: true
}
]
}
var option = {
series: [
{
......
smooth: true,
lineStyle: {
color: 'green',
type: 'dashed' // 可选值还有 dotted solid
}
}
]
}
var option = {
series: [
{
type: 'line',
data: yDataArr,
areaStyle: {
color: 'pink'
}
}
]
}
var option = {
xAxis: {
type: 'category',
data: xDataArr,
boundaryGap: false
}
}
var yDataArr = [3005, 3003, 3001, 3002, 3009, 3007, 3003, 3001, 3005, 3004, 3001, 3009] // 此时y轴的数据都在3000附近, 每个数之间相差不多
var option = {
xAxis: {
type: 'category',
data: xDataArr
},
yAxis: {
type: 'value'
},
series: [
{
type: 'line',
data: yDataArr
}
]
}
这显然不是我们想要的效果, 因此可以配置上 scale , 让其摆脱0值比例
var option = {
yAxis: {
type: 'value',
scale: true
}
}
<script>
var mCharts = echarts.init(document.querySelector("div")) var xDataArr = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
var yDataArr1 = [120, 132, 101, 134, 90, 230, 210]
var yDataArr2 = [20, 82, 191, 94, 290, 330, 310]
var option = {
xAxis: {
type: 'category',
data: xDataArr
},
yAxis: {
type: 'value',
scale: true
},
series: [{
type: 'line',
data: yDataArr1
}, {
type: 'line',
data: yDataArr2
}]
}
mCharts.setOption(option)
</script>
使用了堆叠图之后:
var option = {
series: [{
type: 'line',
data: yDataArr1,
stack: 'all' ,// series中的每一个对象配置相同的stack值, 这个all可以任意写
},
{
type: 'line',
data: yDataArr2,
stack: 'all' ,// series中的每一个对象配置相同的stack值, 这个all可以任意 写
} ,
] ,
}
蓝色这条线的y轴起点, 不再是y轴, 而是红色这条线对应的点. 所以相当于蓝色是在红色这条线的基础之上进行绘制. 基于前一个图表进行堆叠
折线图更多的使用来呈现数据随时间的『变化趋势』
DOCTYPE html>
<html lang="en">
<head>
<script src="js/echarts.min.js">script>
head>
<body>
<div style="width: 600px;height:400px">div>
<script>
var mCharts = echarts.init(document.querySelector("div")) var option = {}
mCharts.setOption(option)
script>
body>
html>
此时 option 是一个空空如也的对象
var data = [{
"gender": "female",
"height": 161.2,
"weight": 51.6
}, {
"gender": "female",
"height": 167.5,
"weight": 59
}, {
"gender": "female",
"height": 159.5,
"weight": 49.2
}, {
"gender": "female",
"height": 157,
"weight": 63
}, {
"gender": "female",
"height": 155.8,
"weight": 53.6
}, {
"gender": "female",
"height": 170,
"weight": 59
}, {
"gender": "female",
"height": 159.1,
"weight": 47.6
}, {
"gender": "female",
"height": 166,
"weight": 69.8
}, {
"gender": "female",
"height": 176.2,
"weight": 66.8
}, {
"gender": "female",
"height": 160.2,
"weight": 75.2
}, {
"gender": "female",
"height": 172.5,
"weight": 55.2
}, {
"gender": "female",
"height": 170.9,
"weight": 54.2
}, {
"gender": "female",
"height": 172.9,
"weight": 62.5
}, {
"gender": "female",
"height": 153.4,
"weight": 42
}, {
"gender": "female",
"height": 160,
"weight": 50
}, {
"gender": "female",
"height": 147.2,
"weight": 49.8
}, ...此处省略...]
假设这个数据是从服务器获取到的, 数组中的每一个元素都包含3个维度的数据: 性别,身高,体重, 而散点图需要的数据是一个二维数组, 所以我们需要将从服务器获取到的这部分数据,通过代码生成散点图需要的数据
var axisData = []
for (var i = 0; i < data.length; i++) {
var height = data[i].height
var weight = data[i].weight
var itemArr = [height, weight] axisData.push(itemArr)
}
axisData 就是一个二维数组, 数组中的每一个元素还是一个数组, 最内层数组中有两个元素, 一个代表身高, 一个代表体重
var option = {
xAxis: {
type: 'value'
},
yAxis: {
type: 'value'
},
series: [{
type: 'scatter',
data: axisData
}]
}
var option = {
xAxis: {
type: 'value',
scale: true
},
yAxis: {
type: 'value',
scale: true
},
series: [{
type: 'scatter',
data: axisData,
}]
}
这两个配置项都支持固定值的写法, 也支持回调函数的写法
固定值的写法如下:
var option = {
series: [{
type: 'scatter',
data: axisData,
symbolSize: 25,
itemStyle: {
color: 'green',
}
}]
}
回调函数的写法如下:
var option = {
series: [{
type: 'scatter',
data: axisData,
symbolSize: function(arg) {
var weight = arg[1]
var height = arg[0] / 100
// BMI > 28 则代表肥胖, 肥胖的人用大的散点标识, 正常的人用小散点标识
// BMI: 体重/ 身高*身高 kg m
var bmi = weight / (height * height) if (bmi > 28) {
return 20
}
return 5
},
itemStyle: {
color: function(arg) {
var weight = arg.data[1]
var height = arg.data[0] / 100
var bmi = weight / (height * height) if (bmi > 28) {
return 'red'
}
return 'green'
}
}
}]
}
var option = {
series: [{
type: 'effectScatter',
rippleEffect: {
scale: 3
}
}]
}
var option = {
series: [{
type: 'effectScatter',
showEffectOn: 'emphasis',
rippleEffect: {
scale: 3
}
}]
}
散点图可以帮助我们推断出不同维度数据之间的相关性, 比如上述例子中,看得出身高和体重是正相关, 身高越高, 体重越重
散点图也经常用在地图的标注上
直角坐标系的图表指的是带有x轴和y轴的图表, 常见的直角坐标系的图表有: 柱状图 折线图 散点图针对于直角坐标系的图表, 有一些通用的配置
var option = {
grid: {
show: true, // 显示grid
borderWidth: 10, // grid的边框宽度
borderColor: 'red', // grid的边框颜色
left: 100, // grid的位置
top: 100,
width: 300, // grid的大小
height: 150 ,
} ,
}
var option = {
xAxis: {
type: 'category',
data: xDataArr,
position: 'top'
},
yAxis: {
type: 'value',
position: 'right'
}
}
var option = {
xAxis: {
type: 'category',
data: xDataArr
},
yAxis: {
type: 'value'
},
dataZoom: [{
type: 'slider',
xAxisIndex: 0
}, {
type: 'slider',
yAxisIndex: 0,
start: 0,
end: 80
}]
}
需要注意的是, 针对于非直角坐标系图表, 比如饼图 地图 等, 以上三个配置可能就不会生效了
DOCTYPE html>
<html lang="en">
<head>
<script src="js/echarts.min.js">script>
head>
<body>
<div style="width: 600px;height:400px">div>
<script>
var mCharts = echarts.init(document.querySelector("div")) var option = {}
mCharts.setOption(option)
script>
body>
html>
此时 option 是一个空空如也的对象
var pieData = [{
value: 11231,
name: "淘宝",
}, {
value: 22673,
name: "京东"
}, {
value: 6123,
name: "唯品会"
}, {
value: 8989,
name: "1号店"
}, {
value: 6700,
name: "聚美优品"
}]
var option = {
series: [{
type: 'pie',
data: pieData
注意:
var option = {
series: [{
type: 'pie',
data: pieData,
label: {
show: true,
formatter: function(arg) {
return arg.data.name + '平台' + arg.data.value + '元\n' + arg.percent + '%'
}
}
}]
}
var option = {
series: [{
type: 'pie',
data: pieData,
label: {
show: true,
formatter: function(arg) {
return arg.data.name + '平台' + arg.data.value + '元\n' + arg.percent + '%'
}
},
roseType: 'radius'
}]
}
var option = {
series: [
{
type: 'pie',
data: pieData,
selectedMode: 'multiple', // selectedOffset: 30
} ,
] ,
}
var option = {
series: [{
type: 'pie',
data: pieData,
radius: ['50%', '70%']
}]
}
饼图可以很好地帮助用户快速了解不同分类的数据的占比情况
百度地图API : 使用百度地图的 api , 它能够在线联网展示地图, 百度地图需要申请 ak
矢量地图 : 可以离线展示地图, 需要开发者准备矢量地图数据
接下来的实现是通过矢量图的方式来实现的
DOCTYPE html>
<html lang="en">
<head>
<script src="js/echarts.min.js">script>
head>
<body>
<div style="width: 600px;height:400px">div>
<script>
var mCharts = echarts.init(document.querySelector("div")) var option = {}
mCharts.setOption(option)
script>
body>
html>
此时 option 是一个空空如也的对象
$.get('json/map/china.json', function (chinaJson) { })
$.get('json/map/china.json', function (chinaJson) { echarts.registerMap('chinaMap', chinaJson) })
var mCharts = echarts.init(document.querySelector("div")) $.get('json/map/china.json', function(chinaJson) {
echarts.registerMap('chinaMap', chinaJson) var option = {
geo: {
type: 'map', // map是一个固定的值
map: 'chinaMap', //chinaMap需要和registerMap中的第一个参数保持一致
}
};
mCharts.setOption(option)
})
注意: 需要注意的是, 由于在代码中使用了 Ajax , 所以, 关于此文件的打开, 不能以 file 的协议打开, 应该将其置于 HTTP 的服务之下方可正常展示地图
var option = {
geo: {
type: 'map', // map是一个固定的值
map: 'chinaMap',//chinaMap需要和registerMap中的第一个参数保持一致,
roam: true, // 运行使用鼠标进行拖动和缩放
} ,
}
var option = {
geo: {
type: 'map', // map是一个固定的值
map: 'chinaMap',//chinaMap需要和registerMap中的第一个参数保持一致,
roam: true,
label: {
show: true ,
} ,
} ,
}
var option = {
geo: {
type: 'map', // map是一个固定的值
map: 'chinaMap',//chinaMap需要和registerMap中的第一个参数保持一致,
roam: true,
label: {
show: true ,
},
zoom: 0.8, // 地图的缩放比例, 大于1代表放大, 小于1代表缩小
center: [87.617733, 43.792818] ,// 当前视角的中心点,用经纬度表示
} ,
}
$.get('json/map/anhui.json', function (anhuiJson) { })
< script >
var mCharts = echarts.init(document.querySelector("div")) $.get('json/map/anhui.json', function(anhuiJson) {
console.log(anhuiJson) echarts.registerMap('anhui', anhuiJson) var option = {
geo: {
type: 'map',
map: 'anhui',
label: {
show: true
},
zoom: 1.2,
center: [116.507676, 31.752889]
}
};
mCharts.setOption(option)
}) < /script>
DOCTYPE html>
<html lang="en">
<body>
<div style="width: 600px;height:400px;border:1px solid red">div>
<script>
var mCharts = echarts.init(document.querySelector("div")) $.get('json/map/china.json', function(chinaJson) {
echarts.registerMap('chinaMap', chinaJson) var option = {
geo: {
type: 'map',
map: 'chinaMap',
roam: true,
label: {
show: true
}
}
}
mCharts.setOption(option)
})
script>
body>
html>
var airData = [{
name: '北京',
value: 39.92
}, {
name: '天津',
value: 39.13
}, {
name: '上海',
value: 31.22
}, {
name: '重庆',
value: 66
}, {
name: '河北',
value: 147
}, {
name: '河南',
value: 113
}, {
name: '云南',
value: 25.04
}, {
name: '辽宁',
value: 50
}, {
name: '黑龙江',
value: 114
}, {
name: '湖南',
value: 175
}, {
name: '安徽',
value: 117
}, {
name: '山 东',
value: 92
}, {
name: '新疆',
value: 84
}, {
name: '江苏',
value: 67
}, {
name: '浙江',
value: 84
}, {
name: '江西',
value: 96
}, {
name: '湖北',
value: 273
}, {
name: '广西',
value: 59
}, {
name: '甘肃',
value: 99
}, {
name: '山西',
value: 39
}, {
name: '内蒙古',
value: 58
}, {
name: '陕西',
value: 61
}, {
name: '吉林',
value: 51
}, {
name: '福建',
value: 29
}, {
name: '贵州',
value: 71
}, {
name: '广东',
value: 38
}, {
name: '青海',
value: 57
}, {
name: '西藏',
value: 24
}, {
name: '四川',
value: 58
}, {
name: '宁夏',
value: 52
}, {
name: '海南',
value: 54
}, {
name: '台湾',
value: 88
}, {
name: '香港',
value: 66
}, {
name: '澳门',
value: 77
}, {
name: '南海诸岛',
value: 55
}]......
var option = {
......series: [{
data: airData
}]
}
var option = {
series: [{
data: airData,
geoIndex: 0,
type: 'map'
}]
}
var option = {
geo: {
type: 'map',
map: 'chinaMap',
roam: true,
label: {
show: true
}
},
series: [{
data: airData,
geoIndex: 0,
type: 'map'
}],
visualMap: {
min: 0, // 最小值
max: 300, // 最大值
inRange: {
color: ['white', 'red'] ,// 颜色的范围
},
calculable: true ,// 是否显示拖拽用的手柄(手柄能拖拽调整选中范围)
} ,
}
var scatterData = [{
value: [117.283042, 31.86119] ,// 散点的坐标, 使用的是经纬度
} ,
]
var option = {
series: [{
data: airData,
geoIndex: 0,
type: 'map'
}, {
data: scatterData,
type: 'effectScatter',
coordinateSystem: 'geo',
rippleEffect: {
scale: 10
}
}]
}
DOCTYPE html>
<html lang="en">
<head>
<script src="js/echarts.min.js">script>
head>
<body>
<div style="width: 600px;height:400px">div>
<script>
var mCharts = echarts.init(document.querySelector("div")) var option = {}
mCharts.setOption(option)
script>
body>
html>
此时 option 是一个空空如也的对象
var dataMax = [{
name: '易用性',
max: 100
}, {
name: '功能',
max: 100
}, {
name: '拍照',
max: 100
}, {
name: '跑分',
max: 100
}, {
name: '续航',
max: 100
}]
var hwScore = [80, 90, 80, 82, 90]
var zxScore = [70, 82, 75, 70, 78]
var option = {
radar: {
indicator: dataMax
},
series: [{
type: 'radar',
data: [{
name: '华为手机1',
value: hwScore
}, {
name: '中兴手机1',
value: zxScore
}]
}]
3.6 .2.雷达图的常见效果
显示数值 label
}
var option = {
series: [{
type: 'radar',
label: {
show: true
},
data: [{
name: '华为手机1',
value: hwScore
}, {
name: '中兴手机1',
value: zxScore
}]
}]
}
var option = {
series: [{
type: 'radar',
label: {
show: true
},
areaStyle: {},
data: [{
name: '华为手机1',
value: hwScore
}, {
name: '中兴手机1',
value: zxScore
}]
}]
}
var option = {
radar: {
indicator: dataMax,
shape: 'circle'
},
series: [{
type: 'radar',
label: {
show: true
},
data: [{
name: '华为手机1',
value: hwScore
}, {
name: '中兴手机1',
value: zxScore
}]
}]
}