一、邂逅ECharts
1. 认识ECharts
- 什么是ECharts
- ECharts(全称EnterpriseCharts)是企业级数据图表。官方解释是:一个基于JavaScript的开源可视化图表库)。
- ECharts可以流畅的运行在PC和移动设备上,兼容当前绝大部分浏览器。
- ECharts底层依赖轻量级的ZRender图形库,可提供直观,生动,可交互,可高度个性化定制的数据可视化图表。
- ECharts的历史
- ECharts由百度团队开源
- 2018年初,捐赠给Apache基金会,成灰Apache软件基金会孵化机项目。
- 2021年1月26日晚,Apache基金会官方宣布ECharts项目正式毕业,称为Apache顶级项目。
- 2021年1月28日,ECharts5线上发布会举行。
- ECharts应用场景
- 智慧城市、园区、航运、公安、机房、监所、电力、物业、应急管理等多个领域的数据可视化展示。
2. ECharts的特点
- 丰富的图表类型
- 提供开箱即用的20多种图表和十几种组件,并且支持各种图表以及组件的任意组合;
- 强劲的渲染引擎
- Canvas、SVG双引擎一键切换,增量渲染等技术实现千万级数据的流畅交互;
- 简单易容,上手容易
- 直接通过便携配置,便可以生成各种图表,并且支持多种集成方式;
- 活跃的社区
- 活跃的社区用户保证了项目的健康发展,也贡献了丰富的第三方插件满足不同场景的需求。
二、ECharts5初体验
1. 集成ECharts的常见方式
- 通过npm获取echarts
npm install echarts --save
2. 初体验ECharts
const myChart = echarts.init(document.getElementById("main"))
var option = {
title: {
text: "ECharts 入门示例"
},
tooltip: {},
legend: {
data: ["销量"]
},
xAxis: {
data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
},
yAxis: {},
series: [
{
name: "销量",
type: "bar",
data: [5, 20, 36, 10, 10, 20]
}
]
}
myChart.setOption(option)
三、ECharts组件和配置
1.ECharts渲染
- 渲染原理
- 浏览器端的图表库大多会选择SVG或者Canvas进行渲染。
- ECharts最开始时一直都是使用Canvas绘制图表,直到ECharts v4.0版本,才发布SVG渲染器。
- SVG和Canvas这两种使用方式在技术上是有很大的差异的,EChart能够做到同时支持,主要归功于ECharts底层库ZRender的抽象和实现。
- ZRender是二维轻量级的绘图引擎,它提供Canvas、SVG、VML等多种渲染方式。
- 因此,ECharts可以轻松的互换SVG渲染器和Canvas渲染器。切换渲染器只须在初始化图表时设置renderer参数为canvas或svg即可。
- 渲染器的选择
- Canvas更适合绘制图形元素较多的图表。
- SVG具有重要的优势:它的内存占用更低、适配性、扩展性好,放大缩小图表不会模糊。
- 在软硬件环境较差,出现性能问题需要优化的场景下,可以通过试验来确定使用哪种渲染器。
- 在需要创建很多ECharts实例且浏览器易崩溃的情况下,可以使用SVG渲染器来进行改善。
- 数据量较大(经验判断 > 1K)、较多交互时,建议选择Canvas渲染器。
2. option配置项(组件)
- backgroundColor:设置直角坐标系内绘图区域的背景
- grid选项:直角坐标系内绘图区域
- show:是否显示直角坐标系网格。boolean类型。
- left、right、top、bottom:grid组件离容器左右上下的距离。string|number类型。
- containLabel:grid区域是否包含坐标轴的刻度标签。boolean类型。
- backgroundColor:Color类型,网格背景色,默认透明。
- xAxis选项:直角坐标系grid中的x轴
- show:是否显示x轴。boolean类型。
- name:坐标轴名称。
- type:坐标轴类型。string类型。
- value 数值轴,适用于连续数据。
- category 类目轴,适用于离散的类目数据。
- data:类目数据,在类目轴中有效。array类型。
- axisLine:坐标轴轴线相关设置。object类型。
- axiosTick:坐标轴刻度相关设置。object类型。
- axisLabel:坐标轴刻度标签相关设置。object类型。
- splitLine:坐标轴在grid区域中的分隔线。object类型。
- yAxis选项:直角坐标系grid中的y轴
- title:图表的标题
- legend:图例,展示了不同系列的标记、颜色和名字
- tooltip:提示框
- toolbox:工具栏,提供操作图表的工具
- series:系列,配置系列图表的类型和图形信息数据
- name:系列名称,用于tooltip的显示,legend的图例筛选等。
- type:指定系列图表的类型。
- data:系列中的数值内容数组。数组中的某一项称为数据项。
- label:图形上的文本标签。
- itemStyle:图形样式。
- emphasis:高亮的图形样式和标签样式。
- coordinateSystem:该系列使用的坐标系,默认值为二维的直角坐标系。
- visualMap:视觉映射,可以将数据映射到图形的形状、大小、颜色等
- geo:地理坐标系组件。用于地图的绘制,支持在地图坐标系上绘制散点图,线集。
四、ECharts图表实战
1. 柱形图
var myChart = echarts.init(document.getElementById("main"))
var option = {
backgroundColor: "rgb(40, 46, 72)",
grid: {
left: "5%",
right: "6%",
top: "30%",
bottom: "5%",
containLabel: true,
},
tooltip: {},
xAxis: {
name: "",
axisLine: {
show: true,
lineStyle: {
color: "#42A4FF"
}
},
axisTick: {
show: false
},
axisLabel: {
color: "white"
},
data: ["一月", "二月", "三月", "四月", "五月", "六月", "七月"]
},
yAxis: {
name: "个",
nameTextStyle: {
color: "white",
fontSize: 13,
},
axisLine: {
show: true,
lineStyle: {
color: "#42A4FF",
},
},
axisTick: {
show: false,
},
splitLine: {
show: true,
lineStyle: {
color: "#42A4FF",
},
},
axisLabel: {
color: "white",
},
},
series: [
{
name: "销量",
type: "bar",
barWidth: 17,
itemStyle: {
color: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "#01B1FF",
},
{
offset: 1,
color: "#033BFF",
},
],
global: false,
},
},
data: [500, 2000, 3600, 1000, 1000, 2000, 4000],
},
]
}
myChart.setOption(option);
2. 折线图
var myChart = echarts.init(document.getElementById("main"))
var option = {
backgroundColor: "rbg(40,46,72)",
grid: {
left: "5%",
right: "1%",
top: "20%",
bottom: "15%",
containLabel: true,
},
legend: {
bottom: "5%",
itemGap: 20,
itemWidth: 13,
itemHeigth: 12,
textStyle: {
color: "#64BCFF",
},
icon: "rect",
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "line",
lineStyle: {
color: "#20FF89",
},
},
},
xAxis: [
{
type: "category",
axisLine: {
show: false,
},
axisLabel: {
color: "#64BCFF",
},
splitLine: {
show: false,
},
axisTick: {
show: false,
},
data: [
"1月",
"2月",
"3月",
"4月",
"5月",
"6月",
"7月",
"8月",
"9月",
"10月",
"11月",
"12月",
],
},
],
yAxis: [
{
type: "value",
splitLine: {
show: false,
},
axisLine: {
show: false,
},
axisLabel: {
show: true,
color: "#64BCFF",
},
},
],
series: [
{
name: "正常",
type: "line",
smooth: true,
symbolSize: 5,
showSymbol: false,
itemStyle: {
color: "#20FF89",
},
areaStyle: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: "#20FF89",
},
{
offset: 1,
color: "rgba(255, 255, 255, 0)",
},
],
false
),
},
data: [200, 200, 191, 234, 290, 330, 310, 201, 154, 190, 330, 410],
},
{
name: "异常",
type: "line",
smooth: true,
symbolSize: 5,
showSymbol: false,
itemStyle: {
color: "#EA9502",
},
areaStyle: {
color: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "#EA9502",
},
{
offset: 1,
color: "rgba(255, 255, 255, 0)",
},
],
},
},
data: [500, 300, 202, 258, 280, 660, 320, 202, 308, 280, 660, 420],
},
],
};
myChart.setOption(option);
3. 饼图
var myChart = echarts.init(document.getElementById("main"))
let pieDatas = [
{
value: 100,
name: "广州占比",
percentage: "5%",
color: "#34D160",
},
{
value: 200,
name: "深圳占比",
percentage: "4%",
color: "#027FF2",
},
{
value: 300,
name: "东莞占比",
percentage: "8%",
color: "#8A00E1",
},
{
value: 400,
name: "佛山占比",
percentage: "10%",
color: "#F19610",
},
{
value: 500,
name: "中山占比",
percentage: "20%",
color: "#6054FF",
},
{
value: 600,
name: "珠海占比",
percentage: "40%",
color: "#00C6FF",
},
];
var data = pieDatas.map((item) => {
return {
value: item.value,
name: item.name,
itemStyle: {
color: item.color,
},
};
});
let total = pieDatas.reduce((a, b) => {
return a + b.value * 1;
}, 0);
var option = {
backgroundColor: "rbg(40,46,72)",
title: {
text: `充电桩总数`,
top: "50%",
left: "50%",
padding: [-20, 0, 0, -45],
textStyle: {
fontSize: 19,
color: "white",
},
subtext: `{totalSty|${total}}`,
subtextStyle: {
rich: {
totalSty: {
fontSize: 19,
color: "white",
width: 90,
align: "center",
},
},
},
},
legend: {
orient: "vertical",
right: "10%",
top: "18%",
itemGap: 20,
itemWidth: 16,
itemHeigth: 16,
icon: "rect",
formatter: function (name) {
var currentItem = pieDatas.find((item) => item.name === name);
return (
"{nameSty|" +
currentItem.name +
"}\n" +
"{numberSty|" +
currentItem.value +
"个 }" +
"{preSty|" +
currentItem.percentage +
"}"
);
},
textStyle: {
rich: {
nameSty: {
fontSize: 12,
color: "#FFFFFF",
padding: [10, 14],
},
numberSty: {
fontSize: 12,
color: "#40E6ff",
padding: [0, 0, 0, 14],
},
preSty: {
fontSize: 12,
color: "#40E6ff",
},
},
},
},
series: [
{
type: "pie",
center: ["50%", "50%"],
radius: ["30%", "75%"],
label: {
show: false,
},
data: data,
roseType: "area",
},
],
};
myChart.setOption(option);
4. 地图
- 绘制地图的两种方式
echarts.registerMap("中国", { geoJSON: china_geojson })
var myChart = echarts.init(document.getElementById("main"))
var option = {
geo: {
map: "china"
}
};
myChart.setOption(option);
var myChart = echarts.init(document.getElementById("main"))
var option = {
series: [
{
type: "map",
map: "中国"
}
]
};
myChart.setOption(option);
- geo地图和series地图区别
- geo会生成一个geo地理坐标系组件,支持在地理坐标系上绘制散点图、线集,可以供其他系列复用。
- series会生成自己内部专用的geo地理坐标系组件,地图主要用于地理区域数据的可视化,配合data使用。
- 地图-着色
echarts.registerMap("中国", { geoJSON: china_geojson })
var myChart = echarts.init(document.getElementById("main"))
var option = {
geo: {
map: "中国",
roam: false,
label: {
show: false
},
aspectScale: 0.75,
itemStyle: {
areaColor: "#023677",
borderColor: "#1180c7",
},
emphasis: {
itemStyle: {
areaColor: "#4499d0",
},
label: {
color: "white",
},
}
}
}
myChart.setOption(option);
echarts.registerMap("中国", { geoJSON: china_geojson })
var myChart = echarts.init(document.getElementById("main"))
var data = [
{ name: "北京", value: 199 },
{ name: "天津", value: 42 },
{ name: "河北", value: 102 },
{ name: "山西", value: 81 },
{ name: "内蒙古", value: 47 },
{ name: "辽宁", value: 67 },
{ name: "吉林", value: 82 },
{ name: "黑龙江", value: 123 },
{ name: "上海", value: 24 },
{ name: "江苏", value: 92 },
{ name: "浙江", value: 114 },
{ name: "安徽", value: 109 },
{ name: "福建", value: 116 },
{ name: "江西", value: 91 },
{ name: "山东", value: 119 },
{ name: "河南", value: 137 },
{ name: "湖北", value: 116 },
{ name: "湖南", value: 114 },
{ name: "重庆", value: 91 },
{ name: "四川", value: 125 },
{ name: "贵州", value: 62 },
{ name: "云南", value: 83 },
{ name: "西藏", value: 9 },
{ name: "陕西", value: 80 },
{ name: "甘肃", value: 56 },
{ name: "青海", value: 10 },
{ name: "宁夏", value: 18 },
{ name: "新疆", value: 180 },
{ name: "广东", value: 123 },
{ name: "广西", value: 59 },
{ name: "海南", value: 14 },
];
var option = {
tooltip: {},
grid: {},
visualMap: [
{
left: "20%",
seriesIndex: [0],
inRange: {
color: ["#04387b", "#467bc0"],
},
},
],
series: [{
name: "中国地图",
type: "map",
map: "中国",
itemStyle: {
areaColor: "#023677",
borderColor: "#1180c7",
},
emphasis: {
itemStyle: {
areaColor: "#4499d0",
},
label: {
color: "white",
},
},
select: {
label: { color: "white" },
itemStyle: { areaColor: "#4499d0" },
},
data
}]
}
myChart.setOption(option);
echarts.registerMap("中国", { geoJSON: china_geojson })
var myChart = echarts.init(document.getElementById("main"))
var mapName = "中国"
var data = [
{ name: "北京", value: 199 },
{ name: "天津", value: 42 },
{ name: "河北", value: 102 },
{ name: "山西", value: 81 },
{ name: "内蒙古", value: 47 },
{ name: "辽宁", value: 67 },
{ name: "吉林", value: 82 },
{ name: "黑龙江", value: 123 },
{ name: "上海", value: 154 },
{ name: "江苏", value: 102 },
{ name: "浙江", value: 114 },
{ name: "安徽", value: 109 },
{ name: "福建", value: 116 },
{ name: "江西", value: 91 },
{ name: "山东", value: 119 },
{ name: "河南", value: 137 },
{ name: "湖北", value: 116 },
{ name: "湖南", value: 114 },
{ name: "重庆", value: 101 },
{ name: "四川", value: 125 },
{ name: "贵州", value: 62 },
{ name: "云南", value: 83 },
{ name: "西藏", value: 9 },
{ name: "陕西", value: 80 },
{ name: "甘肃", value: 56 },
{ name: "青海", value: 10 },
{ name: "宁夏", value: 18 },
{ name: "新疆", value: 120 },
{ name: "广东", value: 193 },
{ name: "广西", value: 59 },
{ name: "海南", value: 14 },
];
var geoCoordMap = {};
myChart.showLoading();
var mapFeatures = echarts.getMap(mapName).geoJson.features;
mapFeatures.forEach(function (v) {
var name = v.properties.name;
geoCoordMap[name] = v.properties.cp;
});
myChart.hideLoading();
console.log("data=>", data);
console.log("geoCoordMap=>", geoCoordMap);
var convertData = function (data) {
var res = [];
for (var i = 0; i < data.length; i++) {
var geoCoord = geoCoordMap[data[i].name];
if (geoCoord) {
res.push({
name: data[i].name,
value: [...geoCoord, data[i].value],
});
}
}
console.log("res=>", res);
return res;
};
var option = {
tooltip: {},
visualMap: {
left: "20%",
seriesIndex: [0],
inRange: {
color: ["#04387b", "#467bc0"],
},
},
geo: {
map: "中国",
roam: false,
label: { show: false },
aspectScale: 0.75,
itemStyle: {
areaColor: "#023677",
borderColor: "#1180c7",
},
emphasis: {
itemStyle: { areaColor: "#4499d0" },
label: { color: "white" },
},
},
series: [
{
name: "中国地图",
type: "map",
map: "中国",
data,
itemStyle: {
areaColor: "#023677",
borderColor: "#1180c7",
},
emphasis: {
itemStyle: { areaColor: "#4499d0" },
label: { color: "white" },
},
select: {
label: { color: "white" },
itemStyle: { areaColor: "#4499d0" },
},
},
{
name: "散点图充电桩",
type: "effectScatter",
geoIndex: 0,
coordinateSystem: "geo",
data: convertData(data),
symbolSize: function (val) {
return val[2] / 10;
},
itemStyle: {
color: "yellow",
shadowBlur: 10,
shadowColor: "yellow",
},
tooltip: {
show: true,
trigger: "item",
formatter: function (params) {
console.log(params);
var data = params.data;
return `${params.seriesName} <div style="margin:5px 0px;"/> ${data.name} ${data.value[2]}`;
},
},
},
],
};
myChart.setOption(option);
五、ECharts其他补充
1. ECharts常见API
- 全局echarts对象
- echarts.init(dom, theme, opts):创建echartsInstance实例
- echarts.registerMap(mapName, opts):注册地图
- echarts.getMap(mapName):获取已注册地图
- 通过echarts.init创建的实例(echartsInstance)
- echartsInstance.setOption(opts):设置图表实例的配置项以及数据,万能接口
- echartsInstance.getWidth/getHeight():获取ECharts实例容器的宽高度
- echartsInstance.resize(opts):改变图表尺寸,在容器大小发生改变时需要手动调用
- echartsInstance.showLoading/hideLoading():显示和隐藏加载动画效果
- echartsInstance.dispatchAction():触发图表行为
- echartsInstance.dispose:销毁实例,销毁后实例无法再被使用
- echartsInstance.on():通过on方法添加事件处理函数
2. 响应式ECharts图表
- 响应式图表的实现步骤
- 图表只设置高度,宽度设置为100%或者不设置;
- 监听窗口的resize事件,即监听窗口尺寸的变化(需节流);
- 当窗口大小发生改变时,然后调用echartsInstance.resize改变图表的大小。
window.addEventListener("resize", function () {
myChart.resize()
})