备考数据可视化的那段时间,不知道为什么总喜欢在很晚的时候看文档。
窗外安静,屏幕亮着,翻着翻着就忽然觉得——ECharts 这个东西,好像不太一样。
它不像平时写 Java 或者 Python,不是在命令计算机”先做这个,再做那个”。更像是在填一张小表格。你把标题放进 title,把坐标轴放进 xAxis,把数据放进 series,然后图就出来了。很乖,不问多余的问题。
后来想通了:ECharts 不需要死背。先把骨架记住,再根据图表类型换零件就好。外套不一样,人还是那个人。
一、通用骨架
大部分图表都长这样:
1 2 3 4 5 6 7 8 9 10 11 12
| var option = { title: { text: '图表标题' }, tooltip: {}, legend: { data: ['系列名称'] }, xAxis: { type: 'category', data: ['A', 'B', 'C'] }, yAxis: { type: 'value' }, series: [{ name: '系列名称', type: 'bar', data: [10, 20, 30] }] };
|
需要记住的字段只有六个:
1 2 3 4 5 6
| title tooltip legend xAxis yAxis series
|
其中 series 是整张图的心脏。图是柱状图、折线图、饼图,还是散点图,就看 type 写什么。换一个词,图表就换了一副模样。
二、柱状图和折线图
这两个最省心,就像填空题。
1 2 3 4 5 6 7 8 9 10 11
| xAxis: { type: 'category', data: ['一月', '二月', '三月'] }, yAxis: { type: 'value' }, series: [{ type: 'bar', data: [120, 200, 150] }]
|
category 和 value 的区别,记这一句话就够:
1 2
| category 是分类,自己写 data(月份、城市、科目这种) value 是数值,ECharts 自己算刻度,不用写
|
如果想把柱状图和折线图叠在一起,在 series 里多放一个对象就行:
1 2 3 4
| series: [ { name: '销量', type: 'bar', data: [120, 200, 150] }, { name: '增长', type: 'line', data: [100, 160, 130] } ]
|
一个 {} 一组图,想叠几个放几个。
三、两个 Y 轴
有时候两组数据的单位不一样,放在同一把尺子上会很奇怪。这时候可以写两个 Y 轴:
1 2 3 4 5 6 7 8 9 10 11 12 13
| yAxis: [ { type: 'value', name: '销量' }, { type: 'value', name: '增长率' } ], series: [ { name: '销量', type: 'bar', data: [120, 200, 150] }, { name: '增长率', type: 'line', yAxisIndex: 1, data: [10, 20, 15] } ]
|
重点是 yAxisIndex: 1——数组从 0 开始,所以 1 指的是第二个 Y 轴。
单位一样的话就别写两个了。能简单就简单。
tooltip 是鼠标悬停时弹出来的提示框。不写它图也能跑,但写了读图会舒服很多。
最懒的写法:
有坐标轴的图(柱状图、折线图)常用 trigger: 'axis',鼠标移到某个 x 轴位置,显示整列数据:
1
| tooltip: { trigger: 'axis' }
|
没有坐标轴的图(饼图、漏斗图)用 trigger: 'item',鼠标移到哪个块,显示哪个块:
1 2 3 4
| tooltip: { trigger: 'item', formatter: '{b}: {c}%' }
|
{b} 是名字,{c} 是数值。记住这两个字母就够了。
五、散点图
散点图有点特别——坐标不写在 xAxis 里,而是直接藏在每个数据点里:
1 2 3 4 5
| data: [ [10, 20], [15, 35], [8, 18] ]
|
每一个小数组是一个点:[x值, y值]。
完整写法:
1 2 3 4 5 6 7 8 9 10
| var option = { title: { text: '散点图' }, tooltip: {}, xAxis: { type: 'value' }, yAxis: { type: 'value' }, series: [{ type: 'scatter', data: [[10, 20], [15, 35], [8, 18]] }] };
|
注意 xAxis 和 yAxis 的 type 都是 'value',不需要 data。
六、雷达图
雷达图有自己的一套,不走 xAxis / yAxis,多了一个字段叫 radar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| var option = { title: { text: '雷达图' }, tooltip: {}, radar: { indicator: [ { name: '学习', max: 100 }, { name: '体育', max: 100 }, { name: '社交', max: 100 }, { name: '实践', max: 100 } ] }, series: [{ type: 'radar', data: [{ name: '样本A', value: [80, 70, 90, 60] }] }] };
|
indicator 定义有几根轴,value 填对应的数值,两边一一对应,数量要一样多。
1 2
| radar.indicator 定义轴 series.data.value 填数值
|
七、漏斗图
漏斗图也不需要坐标轴,数据从大到小排列,形状自然就出来了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var option = { title: { text: '漏斗图' }, tooltip: { trigger: 'item', formatter: '{b}: {c}%' }, series: [{ type: 'funnel', data: [ { value: 100, name: '访问' }, { value: 80, name: '浏览' }, { value: 60, name: '咨询' }, { value: 40, name: '下单' }, { value: 20, name: '支付' } ] }] };
|
适合表示”从多到少”的过程。越到后面越窄,像一只很认真在过滤东西的小漏斗。
八、树图
树图的数据是嵌套结构:
1 2 3 4 5 6 7
| { name: '根节点', children: [ { name: '子节点1' }, { name: '子节点2' } ] }
|
有一个坑:如果数据放在 JSON 文件里,不能直接用 <script> 引入,因为 <script> 只认 JS 文件。要用 fetch:
1 2 3 4 5 6 7 8 9 10 11 12 13
| fetch('data.json') .then(res => res.json()) .then(data => { var option = { title: { text: '树图' }, tooltip: { trigger: 'item' }, series: [{ type: 'tree', data: [data] }] }; myChart.setOption(option); });
|
data: [data] 这里要包一层数组——因为 series.data 要数组,但树图的根节点是对象,所以手动套一层中括号。
如果节点太多挤在一起,加这两个字段会舒展很多:
1 2
| orient: 'LR', initialTreeDepth: 2
|
九、关系图
关系图看起来字段多,但核心只有两个:data 写节点,links 写连线。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| series: [{ type: 'graph', layout: 'force', roam: true, label: { show: true }, edgeLabel: { show: true, formatter: '{c}' }, data: [ { name: '节点A', symbolSize: 30 }, { name: '节点B', symbolSize: 30 }, { name: '节点C', symbolSize: 30 } ], links: [ { source: '节点A', target: '节点B', value: '关系1' }, { source: '节点A', target: '节点C', value: '关系2' }, { source: '节点B', target: '节点C', value: '关系3' } ] }]
|
source 是起点,target 是终点,value 是线上显示的文字。edgeLabel.formatter: '{c}' 里的 {c} 就是这个 value。
1 2
| data 写点,links 连线 source 找 target,value 写关系
|
十、地图
地图这里要分清两件事:
第一件事,地图轮廓文件还是用 <script> 引入 JS 文件:
1
| <script src="map/province/guangxi.js"></script>
|
这一步相当于先把”广西这张地图纸”拿出来。
第二件事,地图上要显示的数据,可以直接写数组,也可以用 fetch 读取 JSON 文件。
如果给的是普通数据数组,就这样放进 series.data:
1 2 3 4 5 6 7
| series: [{ type: 'map', map: '广西', roam: true, label: { show: true }, data: data }]
|
如果数据放在 guangxi_map.json 里,就用 fetch 读取:
1 2 3 4 5 6 7 8 9 10 11 12 13
| fetch('guangxi_map.json') .then(res => res.json()) .then(data => { var option = { series: [{ type: 'map', map: '广西', data: data }] };
myChart.setOption(option); });
|
如果要按数值深浅显示颜色,加 visualMap:
1
| visualMap: { min: 100, max: 900 }
|
如果想在地图上叠加散点或航线,用 geo + coordinateSystem: 'geo':
1 2 3
| geo: { map: '广西', roam: true }
coordinateSystem: 'geo'
|
提交时,除了提交代码,还要提交效果图。
效果图可以用 ECharts 自带的 toolbox 导出,所以提交代码时要保留 toolbox 配置,不要删掉它哦。
最常用的是这个:
1 2 3 4 5 6
| toolbox: { show: true, feature: { saveAsImage: {} } }
|
放进 option 里就是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| var option = { title: { text: '柱状图' }, tooltip: {}, toolbox: { show: true, feature: { saveAsImage: {} } }, xAxis: { type: 'category', data: ['一月', '二月', '三月'] }, yAxis: { type: 'value' }, series: [{ type: 'bar', data: [120, 200, 150] }] };
|
页面右上角会出现一个保存图片的小按钮,点一下就能导出效果图。
简易记忆版:
1
| toolbox: { feature: { saveAsImage: {} } }
|
最后,一张小卡片
考试前可以只背这一个骨架:
1 2 3 4 5 6 7 8
| option = { title: {}, tooltip: {}, legend: {}, xAxis: {}, yAxis: {}, series: [{ type: '类型', data: [] }] }
|
再记住哪些图走的是”特殊通道”:
1 2 3 4 5 6 7
| 饼图 / 漏斗图 → 不要 xAxis、yAxis 雷达图 → 多一个 radar 树图 → data: [data],JSON 用 fetch 读 关系图 → data 写节点,links 写连线 地图 → map 指定地图名,fetch 读数据 toolbox → saveAsImage 导出效果图 散点图 → data 写 [[x, y], [x, y]]
|
其实 ECharts 没有那么多需要死记的东西。
它就是一只小抽屉,每个字段都有自己的位置。标题进 title,提示进 tooltip,数据进 series。一开始看会觉得字段很多,但放久了会发现,它们都很安分,不会乱跑。
考试的时候别慌。先把骨架写出来,判断图表类型,再把数据放进正确的位置。
一步一步来,图就亮起来了。