EChart.js 笔记一
一直对数据可视化比较感兴趣,当年 Alibaba 年报晚会上的大屏显示可谓是技惊四座,够震撼,将数据之美展现得淋漓尽致。
国内的前端数据可视化插件中,echart.js 算是热度很高的,也容易上手,算是新手福利吧;D3.js 源于国外,长于定制,看评价多是倾向于这个方面的。先不管这些,先入手 echart.js。
一、安装
大致分两类:
1.<script> 直接引入本地或者cdn上的 echart(.min).js 文件,是本文中使用的方法;
2. npm 获取,详见 点击comb! ;
二、基本使用
1.首先在 body 中准备一个容器:
1 2 | <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM --> < div id="main" style="width: 600px;height:400px;"></ div > |
2.引入 echart.js 文件: <script> 标签引入
3.基本结构(贴个小demo):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <! DOCTYPE html> < html > < head > < meta charset="utf-8"> < title >ECharts</ title > <!-- 引入 echarts.js --> < script src="echarts.min.js"></ script > </ head > < body > <!-- 为ECharts准备一个具备大小(宽高)的Dom --> < div id="main" style="width: 600px;height:400px;"></ div > < script type="text/javascript"> // 基于准备好的dom,初始化echarts实例 var 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); </ script > </ body > |
三、异步加载数据和更新
1.异步加载也比较简单,通过 ajax 请求数据,并将数据和配置填入 setOption 即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | var myChart = echarts.init(document.getElementById( 'main' )); // 显示标题,图例和空的坐标轴 myChart.setOption({ title: { text: '异步数据加载示例' }, tooltip: {}, legend: { data:[ '销量' ] }, xAxis: { // 先声明 data: [] }, yAxis: {}, series: [{ name: '销量' , type: 'bar' , data: [] }] }); // 异步加载数据 $.get( 'data.json' ).done( function (data) { // 填入数据 myChart.setOption({ xAxis: { data: data.categories }, series: [{ // 根据名字对应到相应的系列 name: '销量' , data: data.data }] }); }); |
上面的思路是先将空的坐标系画出来,获取数据后在填入进去,另外一条思路是先获取数据,在配置各项目,代码层面是将 setOption 全部写在 ajax 逻辑内部,但这样很容易造成页面的区域性空白,故不推荐这种思路。
注意:在数据的更新时需要通过 name 属性对应到相应的系列,更推荐在配置时加上 series 中的 name 。
2.对于加载过程的优化:
数据加载过程中往往出现各种问题导致加载过程变长,这就很容易产生用户体验问题,echart.js中内置了一个简单加载过渡动画的 api:
请求数据前调用 showLoading 方法,数据加载完成后调用 hideLoading 方法隐藏加载动画即可。
1 2 3 4 5 6 7 8 | // 调用 showLoading 方法 myChart.showLoading(); $.get( 'data.json' ).done( function (data) { // 调用 hideLoading 方法 myChart.hideLoading(); myChart.setOption(...); }); |
3.数据的动态更新
使用定时器(setInterval)定时请求数据并更新 setOption 即可。 动态更新实例
四、dataset 管理数据
Echart 4 以前,数据需要在各个 series 中声明,这中方式直观易理解,但是缺点是不利于多个系列共享等。
而从 4 开始,提供数据集(dataset)来声明数据,可以完成诸如:共享、分割数据等操作。
官方的入门例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | option = { legend: {}, tooltip: {}, 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 系列,默认情况下,每个系列会自动对应到 dataset 的每一列。 series: [ {type: 'bar' }, {type: 'bar' }, {type: 'bar' } ] } |
或者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | option = { legend: {}, tooltip: {}, dataset: { // 这里指定了维度名的顺序,从而可以利用默认的维度到坐标轴的映射。 // 如果不指定 dimensions,也可以通过指定 series.encode 完成映射,参见后文。 dimensions: [ 'product' , '2015' , '2016' , '2017' ], source: [ {product: 'Matcha Latte' , '2015' : 43.3, '2016' : 85.8, '2017' : 93.7}, {product: 'Milk Tea' , '2015' : 83.1, '2016' : 73.4, '2017' : 55.1}, {product: 'Cheese Cocoa' , '2015' : 86.4, '2016' : 65.2, '2017' : 82.5}, {product: 'Walnut Brownie' , '2015' : 72.4, '2016' : 53.9, '2017' : 39.1} ] }, xAxis: {type: 'category' }, yAxis: {}, series: [ {type: 'bar' }, {type: 'bar' }, {type: 'bar' } ] }; |
建议: dataset 中 source 是数组,建议将数据模拟成 二维 排列,这样在整个 dataset 的学习过程中比较容易理解。
行、列映射
dataset 的 source 中数据可以大致看成是一个二维排列的数组,那是怎么将数组中的数据与图表对应的呢?
1 2 3 4 5 | 用户可以使用 seriesLayoutBy 配置项,改变图表对于行列的理解。seriesLayoutBy 可取值: 'column' : 默认值。系列被安放到 dataset 的列上面。 'row' : 系列被安放到 dataset 的行上面。 |
官方栗子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | option = { legend: {}, tooltip: {}, dataset: { source: [ [ 'product' , '2012' , '2013' , '2014' , '2015' ], [ 'Matcha Latte' , 41.1, 30.4, 65.1, 53.3], [ 'Milk Tea' , 86.5, 92.1, 85.7, 83.1], [ 'Cheese Cocoa' , 24.1, 67.2, 79.5, 86.4] ] }, xAxis: [ {type: 'category' , gridIndex: 0}, // 坐标系1 {type: 'category' , gridIndex: 1} // 坐标系2 ], yAxis: [ {gridIndex: 0}, // 坐标系1 {gridIndex: 1} // 坐标系2 ], grid: [ {bottom: '55%' }, // 坐标系1 距离底部距离 {top: '55%' } // 坐标系2 距离顶部距离 ], series: [ // 这几个系列会在第一个直角坐标系中,每个系列对应到 dataset 的每一行,即将 source 中的行作为 x 轴。 {type: 'bar' , seriesLayoutBy: 'row' }, {type: 'bar' , seriesLayoutBy: 'row' }, {type: 'bar' , seriesLayoutBy: 'row' }, // 这几个系列会在第二个直角坐标系中,每个系列对应到 dataset 的每一列。 {type: 'bar' , xAxisIndex: 1, yAxisIndex: 1}, {type: 'bar' , xAxisIndex: 1, yAxisIndex: 1}, {type: 'bar' , xAxisIndex: 1, yAxisIndex: 1}, {type: 'bar' , xAxisIndex: 1, yAxisIndex: 1} ] } |
数据映射到图形(encode)
官方栗子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | var option = { dataset: { source: [ [ 'score' , 'amount' , 'product' ], [89.3, 58212, 'Matcha Latte' ], [57.1, 78254, 'Milk Tea' ], [74.4, 41032, 'Cheese Cocoa' ], [50.1, 12755, 'Cheese Brownie' ], [89.7, 20145, 'Matcha Cocoa' ], [68.1, 79146, 'Tea' ], [19.6, 91852, 'Orange Juice' ], [10.6, 101852, 'Lemon Juice' ], [32.7, 20112, 'Walnut Brownie' ] ] }, // 注意下面两行的写法; xAxis: {}, yAxis: {type: 'category' }, series: [ { type: 'bar' , encode: { // 将 "amount" 列映射到 X 轴。 x: 'amount' , // 将 "product" 列映射到 Y 轴。 y: 'product' } } ] }; |
放一个官网实例(数据量巨大): 数据图 ;
encode 的具体配置以及值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | // 例如在直角坐标系(grid/cartesian)中: encode: { // 把 “维度1”、“维度5”、“名为 score 的维度” 映射到 X 轴: x: [1, 5, 'score' ], // 把“维度0”映射到 Y 轴。 y: 0, // 使用 “名为 product 的维度” 和 “名为 score 的维度” 的值在 tooltip 中显示 tooltip: [ 'product' , 'score' ] // 使用 “维度 3” 的维度名作为系列名。(有时候名字比较长,这可以避免在 series.name 重复输入这些名字) seriesName: 3, // 表示使用 “维度2” 中的值作为 id。这在使用 setOption 动态更新数据时有用处,可以使新老数据用 id 对应起来,从而能够产生合适的数据更新动画。 itemId: 2, // 指定数据项的名称使用 “维度3” 在饼图等图表中有用,可以使这个名字显示在图例(legend)中。 itemName: 3 } // 对于极坐标系,可以是: encode: { radius: 3, angle: 2, ... } // 对于地理坐标系,可以是: encode: { lng: 3, lat: 2 } // 对于一些没有坐标系的图表,例如饼图、漏斗图等,可以是: encode: { value: 3 } |
实例:
1.南丁格尔(饼)图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | <! DOCTYPE html> < html lang="zh"> < head > < meta charset="UTF-8"> < meta name="viewport" content="width=device-width, initial-scale=1.0"> < meta http-equiv="X-UA-Compatible" content="ie=edge"> < title >echart-coxcomb</ title > </ head > < body > < p >南丁格尔图是饼图的一种</ p > < div id="main" style="width: 600px;height: 400px;"></ div > < script type="text/javascript" src="../../jslib/echarts.js"></ script > < script type="text/javascript"> // 初始化 echart 实例 var myChart = echarts.init(document.getElementById('main')); // 指定图表的配置项和数据 var option = { // 设置全局背景色,注意与下面阴影的关系 backgroundColor: '#2c343c', // 将数据映射到扇形的明暗程度上 visualMap: { show: false, min: 80, max: 600, inRange: { colorLightness: [0, 1] } }, series: [ { name: '访问来源', type: 'pie', // 通过 type 来控制图表种类 radius: '75%', // 图表大小 data: [ {value: 235, name: '视频广告'}, {value: 274, name: '联盟广告'}, {value: 310, name: '邮件营销'}, {value: 335, name: '直接访问'}, {value: 400, name: '搜索引擎'} ], roseType: 'angle', // 将饼图以南丁格尔图形式展示 itemStyle: { normal: { // 饼图扇形的颜色 color: '#c23531', // 设置阴影大小 shadowBlur: 100, // 设置阴影颜色 shadowColor: 'rgba(0,0,0,0.5)' } }, label: { normal: { // 文本标签的字体颜色 color: 'rgba(255, 255, 255, 0.3)' } }, labelLine: { normal: { // 文本标签的视觉引导线颜色 lineStyle: { color: 'rgba(255, 255, 255, 0.3)' } } } } ] }; // 使用配置项并显示图像 myChart.setOption(option); </ script > </ body > </ html > |
更多关于饼图的配置项详参: echart.js - pie configure ;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现