这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
如果问我参加工作以来,用得最多的库是什么?那一定是Echarts,这不,前段时间刚刚结束了一段疯狂的开发-仪表板,实现最多的就是图表。其实在这之前,我也实现过图表,接下来,我会把实现过程中,踩过的坑,和比较难找的配置项来具体说一下。
本期主要说一下Echarts实现世界地图,其他图表例如半圆环,气泡图,词云图等等,将放在明天来讲。
Echarts实现世界地图
之前写过用Highcharts来实现世界地图,当时踩了很多坑,走了很多弯路。咦,这次又来个需求,实现世界地图,我想这次实现起来可方便了,尽管Highcharts很牛,奈何有他的缺点,大家应该懂。行吧,转到用Echarts,这一路,可没少踩坑。
其中有几个点我一一罗列一下:
- 将世界地图初步展现出来;
- 将世界地图某些国家按照右侧图例,对应颜色展示出来
- 右侧放大缩小按钮来控制地图缩放
- 世界地图上点击任何一个国家,会显示黄色,调整该颜色
- 点击图例后,图例颜色会变浅,做调整
- 点击图例后,再点击某个国家,该国家颜色会有变化,需调整 其实上面提到的几个点,正是我在实现过程中需要解决的问题。接下来一一讲解,会包含我的解决思路及具体实现方案。
将世界地图初步展现出来
我用Echarts做图表有一个规律,一般会先去官方提供的demo引进来,运行成功后调整部分内容,改为自己需要的形式。本次也是一样,因为第一次使用Echarts实现地图功能,所以先拿个demo跑一跑,试一试。
问题1:api.coord is not a function 这一问题困扰了我好久,最终我没有使用该APi。不过还是有一个排查的过程,现在大致来说一下。
api.coord来自于配置项renderItem,好,那就去官网查找该配置项。就是这儿echarts.apache.org/zh/option.h…
现在想来,应该是我没有引入坐标的问题吧(时间原因,我没有具体试,后期找个时间查一下)。
问题2:Echarts实现中国地图只显示title,不显示地图。 基于上述demo无果,我发现官网提供的这个demo是没有api.coord的,我当时想使用这个demo是不是就可以略过上述问题了,因此换为了官网的另一个demo。
使用该demo还算顺利,不报错了,但是只显示了一个title。就是下面这种效果。
原因是没有引入地理坐标系组件。就是下述配置项:echarts.apache.org/zh/option.h…
加上之后,中国地图出现了,但是还不是demo中的样子。因为我不需要打点,所以没有继续处理。
geo: {
// 表示世界地图,中国地图直接改为china
map: 'china',
type: 'effectScatter',
coordinateSystem: 'bmap',
mapType: 'world',
data: convertData(
data
.sort(function (a, b) {
return b.value - a.value;
})
.slice(0, 6)
),
data: convertData(data
.sort(function (a, b) {
return b.value - a.value;
})
.slice(0, 6)),
symbolSize: function (val) {
return val[2] / 10;
},
}
]
}
问题3: 要引入百度地图的AK? 在排查问题的过程中,有的说要申请ak,咱这儿是不需要的。咱们没有直接引百度地图。
将世界地图某些国家按照右侧图例,对应颜色展示出来
先提一下,右侧的图例是如何处理的?
这里用到的配置项是VisalMap,称为:视觉映射组件,具体api地址是:echarts.apache.org/zh/option.h…
该参数又分为连续和分段型。
(1)连续,type值为continuous。样式是这样的:
(2)不连续,type值为piecewise,样式是这样的:
最初我加了连续,在我的世界地图上中国,俄罗斯等四个国家的数据也显示在图中了,但是这不是我想要的效果啊,干脆把那个参数改为了不连续,结果四个国家的数据没有对应了,后来通过pieces参数调整过来了,并且达到了自己想要的效果。
visualMap: {
type: 'piecewise',
left:30,
realtime: false,
calculable : true,
pieces: [
{gte: 100, label: '范围4', symbol: 'circle', color: '#ff523f'},
{gte: 10, lte: 100, label: '范围3', symbol: 'circle', color: '#fab011'},
{gte: 1, lte: 9, label: '范围2', symbol: 'circle', color: '#ffe100'},
{lt: 1, label: '范围1', symbol: 'circle', color: '#67cc02'}
],
},
如果你也是使用官方提供的demo实现的中国地图,那么会发现,series里面有两个对象,另外加上geo,相当于有三个对象。其实用这三个中的一个,就能将中国地图展示出来,你可以试一下,我只试了两个对象。
右侧放大缩小按钮来控制地图缩放
这个比较容易实现,关键可能是调用地图的api,来实现他的放大缩小,具体代码如下:
<div v-if="!loading" class="button-wrapper">
<el-button
size="small"
class="button-grow"
:disabled="currentZoom > 3"
@click="roamMap(0)"
>
<i class="iconfont icon-fangda" />
</el-button>
<el-button
size="small"
class="button-shrink"
:disabled="currentZoom < 1"
@click="roamMap(1)"
>
<i class="iconfont icon-suoxiao" />
</el-button>
</div>
// 地图缩放 flag: 0->放大 1->缩小
roamMap(flag) {
this.currentZoom = this.$refs.worldMapChart.chart.getOption().series[0].zoom; // 当前的缩放比例
let increaseAmplitude = 1.2; // 点击按钮每次 放大/缩小 比例
if (flag == 1) {
increaseAmplitude = 0.8;
}
this.initOption.series[0].zoom = this.currentZoom * increaseAmplitude;
this.$refs.worldMapChart.chart.setOption(this.initOption);
},
世界地图上点击任何一个国家,会显示黄色,调整该颜色
其实在最初,没有找到对应的配置项,最后的最后才发现,唉,Echarts想的还是很全面的,想要实现的内容一定,去找配置项,耐心找。 在series中添加下述代码即可:
select: {
label: {
// 不显示国家名称
show: false
},
itemStyle: {
// 这里可以设置个颜色覆盖掉默认的黄色
areaColor: '#F7F7F7'
}
},
其实在最初找到了一种方案,可以试一下:
// 点击某个国家后,原本默认会显示黄色,现在调整一下
this.$refs.worldMapChart.chart.on('click', function(params) {
if (params?.event?.target?.states?.select?.style) {
params.event.target.states.select.style.fill = params.color ? params.color : '#F7F7F7';
}
});
点击图例后,图例颜色会变浅,做调整
这个也是,有对应api,但是我最初在实现的时候,用了一个笨方法,把原本的图例设置为隐藏,然后写了一个div,覆盖在上面,保证图例无法点击,因为我们的需求其实是不需要点击的。
<div v-if="!loading" class="legend-wrapper">
<el-badge color="#B32424">
<span>范围4</span>
</el-badge>
<el-badge color="#FF3333">
<span>范围3</span>
</el-badge>
<el-badge color="#FF9F40">
<span>范围2</span>
</el-badge>
<el-badge color="#FFCB48">
<span>范围1</span>
</el-badge>
</div>
调整世界地图默认的颜色:
itemStyle: {
// 区域的颜色
areaColor: '#F7F7F7',
// 边框的颜色
borderColor: '#D0D0D0',
// 鼠标悬浮时,选中区域的颜色(默认会显示当前区域展示的颜色)
emphasis: {
areaColor: '#a4edba',
}
}
鼠标悬浮,不在地图上展示国家名称,而是在tooltip中显示:
// 鼠标悬浮的时候,不单独显示国家名称
emphasis: {
label: {
show: false
}
},
基于之前封装的组件,在世界地图完整代码如下:
至此,世界地图就完整地呈现出来了。