写在前面,最近刚好在写一个大屏项目,然后用到了echarts里面的地图和水球图,在实现这些图表的过程中遇到了一些问题,今天一一列举出来并写下解决方案。(地图和页面的样式只做简单的实现)
这边先简单回顾一下echarts实现地图的方式
- 首先需要先安装echarts依赖包,我项目是用vue搭建的,所以只需要在控制台执行
npm install echarts -S
安装最新版本即可。 - 安装完依赖包后,接下来需要拿到你需要画的地图的JSON文件,这边以中国地图为例。该json文件可以网上找第三方的下载,再引入项目中。例如这样的
- 这些东西准备就绪后,就可以在项目中使用它们了,首先引入echarts依赖包和你刚才所下载的geoJson文件,这样一个简单的中国地图就实现了。
js
<template>
<div class="page">
<div id="map"></div>
</div>
</template>
<script>
import * as echarts from "echarts";
import geoJSON from "./assets/mapJson/geoJson.json"
import { onMounted } from 'vue';
export default {
name: "App",
components: {},
setup() {
function drawMap() {
echarts.registerMap('China', {geoJSON: geoJSON})
const dom = document.getElementById("map");
const mapEcharts = echarts.init(dom);
const option = {
series: [
{
left: '15%',
right: '15%',
top: '15%',
bottom: '15%',
layoutSize: '100%',
type: "map",
map: "China"
}
]
}
mapEcharts.setOption(option);
}
onMounted(() => {
drawMap();
})
},
};
</script>
<style lang="scss" scoped>
.page{
width: 100vw;
height: 100vh;
#map{
width: 100%;
height: 100%;
}
}
</style>
好了,现在地图也实现了,列举一下我开发过程中遇到的问题。
- 实现中国地图的过程中,由于页面区域高度有限,想把地图在该块区域以最大比例显示,所以希望地图上南海区域以缩略图显示在地图区域的右下角。
- 地图背景需要用自定义的纹理图实现
- 地图整体看起来不那么扁,希望立体一些
让地图的缩略图显示在区域的右下角
在使用echarts.registerMap("china", {geoJson: geoJson})时,china的第一个字母需要小写,并且option配置项中的series数组中的map属性也需要把china首字母小写。
地图背景需要用自定义图片实现
最开始我想的办法是让UI把图片切出来,然后把该图片当作整个区域的背景图,再在该区域上实现地图,但是这个办法有一个不好的地方就是,需要调整地图的位置使得地图外边框完全覆盖住切图的部分,这个实现起来太过于繁杂,就不了了之。后面查找了echart前面的几个版本,官方有给了实现方式。就是在series数组配置项中配置itemStyle中areaColor的image属性。现在我网上随便找一张图片来充当背景图。
以下是实现方式,关键就这几行代码,特别要注意的是,image的src属性必须是base64格式的,不能用图片的相对路径,不然图片无法显示。
js
charts.registerMap('china', {geoJSON: geoJSON})
const dom = document.getElementById("map");
const mapEcharts = echarts.init(dom);
const img = new Image();
img.src = '****'
const option = {
series: [
{
left: '15%',
right: '15%',
top: '15%',
bottom: '15%',
layoutSize: '100%',
type: "map",
map: "china",
itemStyle: {
areaColor: {
image: img
}
}
}
]
}
img.onload = function() {
mapEcharts.setOption(option);
}
最后实现的效果就如下图所示
地图看起来立体一些
这个问题实现起来就相对麻烦一些,因为前面考虑不用切图当背景图来实现,就想着多画几层地图,然后通过添加阴影,和上下间的位置来实现。这就可以用echarts官方提供的geo属性来实现。对于geo属性,我网上查了一下资料,大概的意思是它能够展示地理坐标系中的点线面。
具体实现步骤如下:
- 把之前在series配置项中的大多数属性移至geo数组中,只留下原先的type、data属性即可,
并在series配置项中新增geoIndex: 0的属性。geoIndex: 0的意思是geo配置项中有多项,我们指定第一层绘制的地图为主。
为什么geo是数组,因为需要让地图看起来更加立体,单单一层是不太够的。
js
//series中的配置信息
series: [
{
type: 'map',
geoIndex: 0,
data: []
}
]
有的人会说,geo配置一层就可以了吧,我让这一层有阴影就可以了吧,那我们来试一下,为了看明显一点,阴影的偏移量为10,颜色为红色。实现的代码如下:
js
geo: [
{
left: '15%',
right: '15%',
top: '15%',
bottom: '15%',
z: 1,
map: "china",
itemStyle: {
areaColor: {
image: img
},
borderColor: 'black',
borderWidth: 2, // 边框的宽度
shadowBlur: 5, // 阴影的大小
shadowBlurY: 10, // 垂直方向上的偏移量
shadowColor: 'red'
}
}
]
该段代码实现的效果图是这样的
大家有没有发现,各个省边缘的边框也会有偏移量,这样就会导致这个地图看起来很丑。 2. 如果设置了多个geo配置项呢,我们来试一下
js
geo: [
{
left: '15%',
right: '15%',
top: '15%',
bottom: '15%',
z: 1,
map: "china",
itemStyle: {
areaColor: {
image: img,
}
}
},
{
left: '15%',
right: '15%',
top: '15%',
bottom: '15%',
z: 0,
map: "china",
itemStyle: {
borderColor: 'black',
borderWidth: 2,
shadowBlur: 10,
shadowBlurY: 20,
shadowColor: 'red'
}
}
]
多个geo配置实现起来是这样的
是不是有立体的效果了,如果大家还有需要,可以自行再多加几层,然后让覆盖层的层级逐级递减,也就是配置项中z的值,离顶部的距离依次减少,就会有更好的立体效果。