具有区域分布特性的数据,通过地图来展示,可以大幅提高数据分析价值。此外数据地理信息分布展示,可以说是数据大屏的必备组件。
文章主要讲解如下内容:
- 轻松入门篇
- 绘制国家、省份、市区地图
- 多级地图下钻的实现
- 搞懂 Map 和 Geo 的区别
- 实用技巧篇
- 地图展示多维数据展示(Series)
- 地图标点(MarkPoint)及其特效展示
- 地理位置间连线(MarkLine)及其特效展示
- 地图结合 Echart 基础图表的应用
- 装逼必备篇
- 数据分布效果(DataRange)
- 自定义图例 Legend 样式
- 自定义标签 Label 样式
- 自定义元素 Item 样式
- 自定义数据格式 Formatter 显示
轻松入门篇
Echarts 是一款开源的、功能丰富的图表库,本文将抽取其中的 Map 模块作较为全面的讲解。Echarts 的图表都是在网页当中显示,目前支持 JavaScript 和 Python,在 Python 中主要是 PyCharts 库提供,本质也是生成 html 在网页中显示。本文将采用目前最新的 5.x 版本的 Echarts ,利用 JavaScript 作实战演练和讲解。
绘制国家、省份、市区地图
本文除了用到 Echarts 库之外,还利用了 JQuery 库。在线引用这两个库:
<script crossorigin=\"anonymous\"integrity=\"sha512-n/4gHW3atM3QqRcbCn6ewmpxcLAHGaDjpEBu4xZd47N0W2oQ+6q7oc3PXstrJYXcbNU1OHdQ1T7pAP+gi5Yu8g==\"src=\"https://lib.baomitu.com/jquery/3.6.0/jquery.js\"></script><script crossorigin=\"anonymous\"integrity=\"sha512-BuAhidfi8Cl0IPjBLyj4ob75IMHmQxoGCm7y0Vabo3xJD+QuDU9QG3ZVJd0QZ0uzTQSChz/iOhRxxbZS1z/F6g==\"src=\"https://lib.baomitu.com/echarts/5.1.2/echarts.js\"></script>
Echarts 绘制图表的固定操作,首先定义一个 dom 节点用于初始化图表。
<div id=\"main\" style=\"width: 100%;height:1000px;\"></div>
获取节点,执行初始化操作:
var chart = echarts.init(document.getElementById(\'main\'));
初始化图表之后,就好像我们得到了一张白纸,现在我们将在这张白纸上绘制我国的大好河山。下一步注册地图:
$.get(\'./china.json\', function (data) { echarts.registerMap(\'china\', data); })
注册国家则需要获取 china.json,对应省市则需要省市的 json 数据,这些 json 数据我都整理了放在我的网盘。
链接:https://pan.baidu.com/s/1i6yhYpMOHsqPrk0CkY1RtQ 提取码:5555
下载下来后,文件夹结构如图所示,包含了全世界、全国已经各个省市的城市数据信息。
地图注册完毕之后,定义 option,并将 option 设置到初始化的图表上去。
$.get(\'./china.json\', function (data) { echarts.registerMap(\'china\', data); var option = { backgroundColor: \'#000\', // 图表背景色 geo: { //这里要保持和前面注册的地图保持一致 map: \"china\", label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } }, } }; chart.setOption(option); })
最终的效果:
到这里我们就把全国的地图绘制好了,option 当中的其他的属性会在后面详细讲解,下面我们绘制一个省的地图看一下,以四川为例,只需要将上面获取的数据改为 sichuan 即可,注意拼音和 json 文件的名字是一一对应的。代码演示:
var chart = echarts.init(document.getElementById(\'main\'));$.get(\'./province/sichuan.json\', function (data) { echarts.registerMap(\'sichuan\', data); var option = { backgroundColor: \'#000\', // 图表背景色 geo: { //这里要和前面注册时地图名称保持一致 map: \"sichuan\", label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } }, } }; chart.setOption(option); })
现在我们已经可以根据 json 数据绘制国家和省份的地图了,下面我们继续学习如何绘制一下市区的地图,这时候有小伙伴就会问了,刚刚绘制的国家和市区有 json 文件,当然可以绘制了,现在假设我要绘制成都市的地图,我没有那个 json 文件,就没有办法了呀!
所以我们要绘制市区的地图,问题定位到需要获取该市区对应的 json 文件,而恰好阿里云 DATAV 为我们解决了这个问题,而且 DATAV 的数据会定时更新的,确保坐标信息以及城市命名等都是最新的。
我们来看一下该如何使用:
DATAV 地址:http://datav.aliyun.com/tools/atlas/index.html#&lat=33.521903996156105&lng=104.29849999999999&zoom=4
在这个界面上,假设我们要获取成都地图,则点击对应区域的,右边就会更新对应的 json 文件链接,我们可以直接引用该路径,也可以下载来使用,是不是比我前面提供的 json 文件方便多了呀。
下面来看一下 绘制的成都地图代码演示
var chart = echarts.init(document.getElementById(\'main\'));$.get(\'./sichuan-chengdu.json\', function (data) { echarts.registerMap(\'sichuan-chengdu\', data); var option = { backgroundColor: \'#000\', // 图表背景色 geo: { //这里要保持和前面注册的地图名称一致 map: \"sichuan-chengdu\", label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } }, } }; chart.setOption(option); })
效果:
总结:到这里我们不仅可以绘制全国、省、市区,借助于 DATAV,还可以获取任意区域的 json 格式文件绘制任意区域的地图。
Echarts 多级地图下钻实现
前面我们演示了如何生成国家、省、市的地图,我们来总结一下它们的相同点。
- 注册地图
- option.geo 使用注册的名称
所以如果我们要开发地图下钻功能,就可以通过监听 Echart 地图上的点击事件,根据入参我们就知道选择了对应的省份(直辖市),然后再更新注册的地图和 option.geo。
chart.on(\'click\', function (params) { console.log(params) //todo:更新注册地图的名称和对应的数据,再重新渲染地图}
效果演示:
搞懂 Map 和 Geo 的区别
通过前面的学习,我们已经可以完成各种区域图表的绘制,但是仅仅能绘制图像轮廓那是远远不够的,还需要将数据放入到地图上,这样地图显示才真正的有意义。我们都知道在平面坐标系中通过 x,y 可以确定一个点并标出,以此类推,地图上则根据经纬度即可确定一个点,除此之外,定位地图上的某一点还可以根据区域的名称进行定位,例如北京,然后标记北京这个点的数据。因此要在地图上标记一个特征点,就有两种方式,这就是下文要说的 Map 和 Geo。
先来看一下 Map 是怎么玩的,就拿全国地图为例,假设我这里有一批遍布全国的销售数据,需要根据省份标定对应的销售数据。数据格式是这样的:
sale_data = [ { name:\"北京\", value:123 }]
下面我需要将这个点在地图上标记出来,下面在 option 的 series 属性填充数据。代码如下:
var chart = echarts.init(document.getElementById(\'main\'));$.get(\'./china.json\', function (data) { echarts.registerMap(\'china\', data); var sale_data = [ { name: \"北京\", value: 123 } ]; var option = { backgroundColor: \'#000\', // 图表背景色 geo: { //这里要保持和前面注册的地图保持一致 map: \"china\", }, tooltip: { triggerOn: \"click\", trigger: \'item\', }, series: [ { name: \'中国\', // series 名称 type: \'map\', // series 图表类型 mapType: \"china\", data: sale_data, label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } }, }, ] }; chart.setOption(option);})
效果演示:
看完了 Map,下面来看一下 Geo 是如何操作的,前面提到了 Map 是通过城市名称去找点,而 Geo 则是通过经纬度去标记。因此我们可以根据 Geo 来标记地图上的任意一点。我这里准备了北京和新疆两个城市的经纬度和数值,数据格式:
geo_data = [ { name: \'北京\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 116.405285, 39.904989, // 地理坐标,经纬度 456 // 北京地区的数值 ] }, { name: \'新疆\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 87.617733, 43.792818, // 地理坐标,经纬度 1000 // 新疆地区的数值 ] }]
代码演示:
var chart = echarts.init(document.getElementById(\'main\'));$.get(\'./china.json\', function (data) { console.log(data) echarts.registerMap(\'china\', data); var sale_data = [ { name: \"北京\", value: 123 } ]; var geo_data= [ { name: \'北京\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 116.405285, 39.904989, // 地理坐标,经纬度 456 // 北京地区的数值 ] } ] var option = { backgroundColor: \'#000\', // 图表背景色 geo: { //这里要保持和前面注册的地图保持一致 map: \"china\", label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } }, }, tooltip: { triggerOn: \"click\", trigger: \'item\', }, series: [ { name: \'mark\', // series 名称 type: \'scatter\', // type: \'effectScatter\', // series 图表类型 coordinateSystem: \'geo\', // series 坐标系类型 data: geo_data, // symbol: \'circle\', // symbolRotate: 100, symbolSize: 15, label: { emphasis: { show: true, formatter: function (param) { return param.data[3]; }, position: \'top\' } }, itemStyle: { normal: { color:\'rgb(255, 0, 255)\' } } }, ] }; chart.setOption(option);})
效果:
总结:通过实践我们就可以看到 Map 和 Geo 两者间的区别,Map 用于根据城市名称找点,Geo 用于根据经纬度位置找点。
实用技巧篇
通过前面的学习,相信小伙伴们现在都应该能够绘制出各种自己想要的图表了。下面我们来继续学习一些有关呈现数据的方法。
地图展示多维数据展示(Series)
处理实际数据的过程中,往往数据有多个维度,这个时候就需要利用 Series 展现多个维度的数据。 以前面讲解的 Geo 根据经纬度定位点为例,再增加一个维度的数据,例如我增加江苏和河南为例:
var geo_data = [ { name: \'北京\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 116.405285, 39.904989, // 地理坐标,经纬度 456 // 北京地区的数值 ] }, { name: \'新疆\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 87.617733, 43.792818, // 地理坐标,经纬度 1000 // 新疆地区的数值 ] } ]; var geo_data2 = [ { name: \'江苏\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 118.767413, 32.041544, // 地理坐标,经纬度 326 // 江苏地区的数值 ] }, { name: \'河南\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 113.665412, 34.757975, // 地理坐标,经纬度 996 // 河南地区的数值 ] } ];
新增的江苏和河南的数据显示,为了区别,我这里用另外一个颜色来展示。
代码示例:
var chart = echarts.init(document.getElementById(\'main\')); $.get(\'./china.json\', function (data) { console.log(data) echarts.registerMap(\'china\', data); var geo_data = [ { name: \'北京\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 116.405285, 39.904989, // 地理坐标,经纬度 456 // 北京地区的数值 ] }, { name: \'新疆\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 87.617733, 43.792818, // 地理坐标,经纬度 1000 // 新疆地区的数值 ] } ]; var geo_data2 = [ { name: \'江苏\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 118.767413, 32.041544, // 地理坐标,经纬度 326 // 江苏地区的数值 ] }, { name: \'河南\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 113.665412, 34.757975, // 地理坐标,经纬度 996 // 河南地区的数值 ] } ]; var option = { backgroundColor: \'#000\', // 图表背景色 geo: { //这里要保持和前面注册的地图保持一致 map: \"china\", label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } }, }, tooltip: { triggerOn: \"click\", trigger: \'item\', }, series: [ { name: \'数据维度 1\', // series 名称 type: \'scatter\', // type: \'effectScatter\', // series 图表类型 coordinateSystem: \'geo\', // series 坐标系类型 data: geo_data, // symbol: \'circle\', // symbolRotate: 100, symbolSize: 15, label: { emphasis: { show: true, formatter: function (param) { return param.data[3]; }, position: \'top\' } }, itemStyle: { normal: { color: \'rgb(255, 0, 255)\' } } }, { name: \'数据维度 2\', // series 名称 // type: \'scatter\', type: \'effectScatter\', // series 图表类型 coordinateSystem: \'geo\', // series 坐标系类型 data: geo_data2, symbol: \'circle\', symbolRotate: 100, symbolSize: 10, label: { emphasis: { show: true, formatter: function (param) { return param.data[3]; }, position: \'top\' } }, itemStyle: { normal: { color: \'rgb(255, 0, 0)\' } } }, ] }; chart.setOption(option); })
效果演示:
地图标点(MarkPoint)及其特效展示
地图标点本质就是散点图,只不过这个坐标系不是我们平时的平面直角坐标系。散点图有 scatter 和 effectScatter 两种表示方式。下面我通过展示两个维度来突出两者间的差别:
var chart = echarts.init(document.getElementById(\'main\')); $.get(\'./china.json\', function (data) { console.log(data) echarts.registerMap(\'china\', data); var geo_data = [ { name: \'北京\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 116.405285, 39.904989, // 地理坐标,经纬度 456 // 北京地区的数值 ] }, { name: \'新疆\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 87.617733, 43.792818, // 地理坐标,经纬度 1000 // 新疆地区的数值 ] } ]; var geo_data2 = [ { name: \'江苏\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 118.767413, 32.041544, // 地理坐标,经纬度 326 // 江苏地区的数值 ] }, { name: \'河南\', // 数据项名称,在这里指地区名称 value: [ // 数据项值 113.665412, 34.757975, // 地理坐标,经纬度 996 // 河南地区的数值 ] } ]; var option = { backgroundColor: \'#000\', // 图表背景色 geo: { //这里要保持和前面注册的地图保持一致 map: \"china\", label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } }, }, series: [ { name: \'数据维度 1\', // series 名称 type: \'scatter\', // 普通散点(气泡)图 coordinateSystem: \'geo\', // 地图坐标系 data: geo_data, symbolSize:15, itemStyle: { normal: { color: \'rgb(0, 255, 0)\'//颜色 } } }, { name: \'数据维度 2\', // series 名称 type: \'effectScatter\', // 带有涟漪特效动画的散点(气泡)图。 coordinateSystem: \'geo\', // 地图坐标系 data: geo_data2, symbol: \'circle\',//图案,支持自定义图案 symbolSize:25, itemStyle: { normal: { color: \'rgb(255, 0, 0)\'//颜色 } } }, ] }; chart.setOption(option); })
效果演示:
从图中可以看出,scatter 表示普通的散点(气泡)图,effectScatter 表示带有涟漪特效动画的散点(气泡)图。scatter 还有很多玩法,有关它们更多的参数,小伙伴们可以参考官方文档这两部分的内容:
scatter:https://echarts.apache.org/zh/option.html#series-scatter
effectScatter:https://echarts.apache.org/zh/option.html#series-effectScatter
地理位置间连线(MarkLine)及其特效展示
同绘制散点图一样,划线在地图坐标系同也同样支持,因为有了前面的基础,我这里就直接上代码演示了:
var chart = echarts.init(document.getElementById(\'main\'));$.get(\'./china.json\', function (data) { console.log(data) echarts.registerMap(\'china\', data); //北京与新疆的连线 var points_bj_xj = []; points_bj_xj.push(); points_bj_xj.push([116.405285, 39.904989]); points_bj_xj.push([87.617733, 43.792818]); //北京与河南的连线 var points_bj_hn = []; points_bj_hn.push([116.405285, 39.904989]); points_bj_hn.push([113.665412, 34.757975]); //北京与江苏的连线 var points_bj_jc = []; points_bj_jc.push([116.405285, 39.904989]); points_bj_jc.push([118.767413, 32.041544]); //连线集合 var myLines = []; myLines.push({ coords: points_bj_xj, name: \'test\', lineStyle: { normal: { color: \'rgb(255,255,0)\' } } }); myLines.push({ coords: points_bj_hn, name: \'test2\', lineStyle: { normal: { color: \'rgb(255,0,0)\' } } }); myLines.push({ coords: points_bj_jc, name: \'test3\', lineStyle: { normal: { color: \'rgb(0,255,255)\' } } }); var option = { backgroundColor: \'#000\', // 图表背景色 geo: { //这里要保持和前面注册的地图保持一致 map: \"china\", label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } }, }, series: [ { type: \'lines\',// 这里还有一个连线其实是做的在线上的一个流动效果,运行代码注意观察你就会看到 coordinateSystem: \'geo\', polyline: true, data: myLines, lineStyle: { normal: { width: 2 } }, effect: { constantSpeed: 20, show: true, trailLength: 0.1, symbolSize: 1.5 }, zlevel:10 } ] }; chart.setOption(option);
效果演示:
最少两点之间连成一条线段,我这里为了演示方便,选取的点比较少,如果线段上有更多的点,则可以绘制出更加细腻的曲线,例如火车行驶路线图等。
地图结合 Echarts 基础图表的应用
通过在地图上直接展示 Echarts 图表(如柱状图、饼状图等),能够非常直观的显示某个区域的数据。下面我以北京市为例,通过柱状图展示北京市每个区的柱状图数据。
首先我们先绘制北京市的地图:
var myChart = echarts.init(document.getElementById(\'main\'));$.ajaxSettings.async = false;$.get(\'./province/beijing.json\', function (data) { echarts.registerMap(\'北京\', data);});$.ajaxSettings.async = true;var option = { // 地图背景颜色 backgroundColor: \'#000\', // 图表背景色 tooltip: { trigger: \'axis\' }, geo: { map: \'北京\', // silent: true, label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } } }, series: []};myChart.setOption(option);
此时地图上没有任何数据,现在准备在每个区域上显示一个柱状图,构造数据如下:
var geoCoordMap = { \"东城区\": [116.418757, 39.937544], \"西城区\": [116.366794, 39.910309], \"朝阳区\": [116.486409, 39.991489], \"丰台区\": [116.286968, 39.863642], \"石景山区\": [116.170445, 39.974601], \"海淀区\": [116.280316, 40.039074], \"门头沟区\": [115.905381, 40.009183], \"房山区\": [115.701157, 39.735535], \"通州区\": [116.758603, 39.802486], \"顺义区\": [116.753525, 40.128936], \"昌平区\": [116.235906, 40.318085], \"大兴区\": [116.338033, 39.658908], \"怀柔区\": [116.607122, 40.524272], \"平谷区\": [117.112335, 40.244783], \"密云区\": [116.943352, 40.477362], \"延庆区\": [115.985006, 40.465325]};var rawData = [ // [\"东城区\",10,20,30], // [\"西城区\",10,20,30], [\"朝阳区\",10,20,30], [\"丰台区\",10,20,30], [\"石景山区\",10,20,30], [\"海淀区\",10,20,30], [\"门头沟区\",10,20,30], [\"房山区\",10,20,30], [\"通州区\",10,20,30], [\"顺义区\",10,20,30], [\"昌平区\",10,20,30], [\"大兴区\",10,20,30], [\"怀柔区\",10,20,30], [\"平谷区\",10,20,30], [\"密云区\",10,20,30], [\"延庆区\",10,20,30]];function makeMapData(rawData) { var mapData = []; for (var i = 0; i < rawData.length; i++) { var geoCoord = geoCoordMap[rawData[i][0]]; if (geoCoord) { mapData.push({ name: rawData[i][0], value: geoCoord.concat(rawData[i].slice(1)) }); } } return mapData;}
在 echarts.setOption()方法前插入如下代码:
function renderEachCity() { var option = { xAxis: [], yAxis: [], grid: [], series: [] }; echarts.util.each(rawData, function(dataItem, idx) { var geoCoord = geoCoordMap[dataItem[0]]; //地图坐标点转为图像上的像素点 var coord = myChart.convertToPixel(\'geo\', geoCoord); console.log(coord) idx += \'\'; inflationData = [30,50,20]; option.xAxis.push({ id: idx, gridId: idx, type: \'category\', name: dataItem[0], nameLocation: \'middle\', nameGap: 3, splitLine: { show: false }, axisTick: { show: false }, axisLabel: { show: false }, axisLine: { onZero: true, lineStyle: { color: \'#666\' } }, data: [\"数据 A\",\"数据 B\",\"数据 C\"], z: 100 }); option.yAxis.push({ id: idx, gridId: idx, splitLine: { show: false }, axisTick: { show: false }, axisLabel: { show: false }, axisLine: { show: false, lineStyle: { color: \'#1C70B6\' } }, z: 100 }); option.grid.push({ id: idx, width: 30, height: 40, left: coord[0] - 15, top: coord[1] - 15, z: 100 }); option.series.push({ // id: idx, type: \'bar\', xAxisId: idx, yAxisId: idx, barGap: 0, barCategoryGap: 0, data: inflationData, z: 100, itemStyle: { normal: { color: function(params){ // 柱状图每根柱子颜色 var colorList = [\'#F75D5D\',\'#59ED4F\',\'#4C91E7\']; return colorList[params.dataIndex]; } } } }); }); myChart.setOption(option);}setTimeout(renderEachCity, 0);
效果演示:
总结:通过这样的方式,我们可以替换柱状图部分的代码,换成任何想要的 Echarts 图表,如饼图、折线图等等,将其展现在地图上,地区数据显示一目了然。
装逼必备篇
通过前面两个章节的学习之后,相信小伙伴们都掌握了如何利用 Echarts 绘制图表并且填入数据了,爱美之心人皆有之嘛,下面我们来继续学习一些能够让地图更加美观的方法。
数据分布效果(DataRange)
数据分布效果能够根据数据的不同,让每个区域显示不同色彩的特点,代码演示通过绘制全国地图,然后每个省份生成一个随机数表示某项数据。通过设置 DataRange 让数据呈现分布排布。
首先我们先来绘制一张全国地图:
var myChart = echarts.init(document.getElementById(\'main\'));//同步获取数据$.ajaxSettings.async = false;$.get(\'./china.json\', function (data) { echarts.registerMap(\'中国\', data);});$.ajaxSettings.async = true;var option = { // 地图背景颜色 backgroundColor: \'#000\', // 图表背景色 tooltip: { trigger: \'axis\' }, geo: { map: \'中国\', // silent: true, label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } } }, series: []};myChart.setOption(option);
此时地图上没有数据,现在我们来给每个省(直辖市)生成随机数(0-9)。修改注册地图部分的代码为:
$.ajaxSettings.async = false;var mapData = [];$.get(\'./china.json\', function (data) { for (x in data.features) { console.log(data.features[x]) mapData.push({ name: data.features[x].properties.name, //生成 0-9 的随机数 value: Math.floor(Math.random() * 10) }) } echarts.registerMap(\'中国\', data);});$.ajaxSettings.async = true;
在 echarts.setOption()
之前,将生成的 mapData 添加到 Series:
option.series.push( { name: \'中国\', // series 名称 type: \'map\', // series 图表类型 mapType: \"中国\", data: mapData, label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } }, });
现在每个省份都有了对应的数据,如图:
可以看到每个省(直辖市)的背景颜色都是一样的,并没有看到差别,此时 DataRange 闪亮登场。在与 Series 平级添加 DataRange:
...dataRange: { //区间的最小值 min: 0, //数据区间的最大值 max: 9, calculable: false, color: [\'#2468a2\', \"#2570a1\", \'#33a3dc\', \'#7bbfea\',], textStyle: { color: \'#000\' }},series:[]...
可以看到颜色越深,数值越大,这样就能形象直观的看到某个区域的数据情况。
自定义图例 Legend 样式
紧接着上一小节,我们通过 DataRange 实现了地图上的分布效果,但是其实还不够完美,因为虽然数据是分布在 0-9 中的,但是假设只想看 5-10 的数据,通过滑动左下角的滑块,也无法做到非常精确的查看。为了解决这一问题,这里引入了自定义 Legend 的方式来解决。
首先还是常规操作,绘制中国地图以及生成根据省份模拟的 0-9 的数据分布,代码演示:
var myChart = echarts.init(document.getElementById(\'main\'));//同步获取数据$.ajaxSettings.async = false;var mapData = [];$.get(\'./china.json\', function (data) { //构造数据 for (x in data.features) { mapData.push({ name: data.features[x].properties.name, //生成 0-9 的随机数 value: Math.floor(Math.random() * 10) }) } echarts.registerMap(\'中国\', data);});$.ajaxSettings.async = true;var option = { // 地图背景颜色 backgroundColor: \'#000\', // 图表背景色 tooltip: { trigger: \'item\' }, geo: { map: \'中国\', // silent: true, label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } } }, dataRange: { min: 0, max: 9, calculable: true, color: [\'#2468a2\', \"#2570a1\", \'#33a3dc\', \'#7bbfea\',], selectedMode: false, textStyle: { color: \'#000\' }, }, series: []};myChart.setOption(option);
效果查看:
下面将数据按照希望的分类方式归类,我这里归为了 0-3,3-6,6-9 三类。归类代码:
var mapDataRange = { data0_3:[], data4_6:[], data7_9:[] } //分类较多的话,建议用 switch case for(x in mapData){ var y = mapData[x].value; if(y>=0 && y <=3){ mapDataRange.data0_3.push(mapData[x]); }else if(y>=4 && y <=6){ mapDataRange.data4_6.push(mapData[x]); }else { mapDataRange.data7_9.push(mapData[x]); } }
向 Option 中定义 ledgend 并定义 legend 的对应的颜色:
option.legend = { orient: \'vertical\', left: \'left\', data:[\'0-3\',\'4-6\',\'7-9\']}option.color = [\'#2468a2\', \"#2570a1\", \'#33a3dc\', \'#7bbfea\',]
向 Series 中填入归类的数据:
for(x in Object.keys(mapDataRange)){ var key = Object.keys(mapDataRange)[x]; var value = mapDataRange[key] key = key.replace(\'data\',\'\').replace(\'_\',\'-\'); option.series.push({ // geoIndex: x, name: key, // series 名称 type: \'map\', // series 图表类型 mapType: \"中国\", data: value, label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 16, // x: \'center\', // textAlign: \'middle\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } } }, itemStyle: { normal: { areaColor: \'#000\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' } }, zlevel: 0 })}
效果演示:
现在假设我只想看数据在 0-3 范围的省份,点击左下角 legend 筛选即可。
总结:这种方式可以实现筛子自定义范围的数据,但是也带来了一定的问题是由于 series 填入了多个维度的 map 数据,会带来数据覆盖问题,底层的省份名称无法显示。
自定义标签 Label 样式
通过设置 Label 演示,能够让元素突出特点展示,例如我们在前演示中在地图上显示每个省份的名字:
label: { normal: { show: true, textStyle: { //颜色 color: \'#fff\', fontSize: 13, x: \'center\', textAlign: \'left\' } }, emphasis: { show: true, textStyle: { color: \'#fff\', fontSize: 13 } }}
分为了两个部分,normal 表示正常显示的样式,emphasis 表示元素被触发时显示的样式。
自定义元素 Item 样式
Item 样式几乎是贯穿整个数据显示的内容,例如我们在前面的演示中,对于 geo 的 itemStyle 设置如下:
itemStyle: { normal: { areaColor: \'#fff\', borderColor: \'dodgerblue\' }, emphasis: { areaColor: \'darkorange\' }}
normal 表示在没有触发的情况下的样式,emphasis 是触发情况下的样式。所以我们会看到这样的一个演示情况:
item 比较容易和 label 混淆,需要注意的是,item 的对应的元素的特点,而 label 是在元素特点的基础的标识。
自定义数据格式 Formatter 显示
数据呈现不完的时候,我们需要借助图像上的一些触发操作展现很多的内容,如图红框所示:
现在我们准备自定义这部分弹出的内容,从而实现我们自己的内容,这就是本章要讲解的 Formatter。首先我们定位到 option 的 tooltip 部分,默认会这样写:
tooltip: { trigger: \'item\'}
现在我们要定义内容,添加 formatter 属性,修改为如下内容:
tooltip: { trigger: \'item\', formatter:function (params) { console.log(params) return \'<div>helloword</div>\'; }},
返回通过组装任意的 html 页面即可。有了页面我们再来分析一下入参 params:
通过打印输入分析可以看出来,该内容就是我们设置的 series 的内容,点击该部分的时候能获取到,基于此再结合可以自由组装 html 页面,所以我们就可以根据 formatter 定义我们想要的任何输出样式。
总结
文章一共分为了三个部分,从绘制地图,然后填充数据,最后的地图美化,通过层层递进的方式讲解,建议上手亲自实践有利于更加有利于掌握。
通过学习,应该能够帮助小伙伴们在绘制地图图表时,解决遇到的绝大部分问题。最后文章有不对的地方欢迎小伙伴们留言指正,感谢你们的订阅。
参考文档
Echarts 官方文档:
https://echarts.apache.org/
GitHub:
https://github.com/flute/echarts3-chinese-map-drill-down