哎哟,说到Echarts地图,我真是有太多话想说了。说实话,刚开始接触这个的时候,我也被那些GeoJSON文件搞得头大,满屏的经纬度坐标看着就像天书一样。但当你真正搞懂它之后,你会发现——哇,这也太酷了吧!自己画出来的地图,每一寸边界都精准得像是从卫星图上抠下来的,那种成就感,啧啧,真的不试一次你都不懂。
今天咱就坐下来,泡杯茶(或者咖啡,看你喜好),我把这些年踩过的坑、总结的套路,一股脑儿全倒出来给你看。咱们不整那些虚头巴脑的官方文档翻译,就聊实实在在能跑起来、能看懂、能改动的东西。
先搞明白:什么是GeoJSON,为啥它这么重要
你知道吗,GeoJSON其实就是一种”地图语言”。想象一下,你要告诉朋友一个地方在哪,你会说”在某某路某某号”,对吧?GeoJSON做的就是类似的事,只不过它说的是经纬度。
一个典型的GeoJSON长这样:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "北京市",
"cp": [116.407526, 39.90403]
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[116.407526, 39.90403],
[116.507526, 39.95403],
[116.607526, 39.90403],
[116.407526, 39.90403]
]
]
}
}
]
}
别被吓到,咱们拆开来揉碎了看。FeatureCollection就是说这是一组特征的集合,features里面装着一个个具体的区域。每个feature都有两个核心部分:properties是属性(比如名字、中心点坐标),geometry是几何形状(也就是边界线怎么画)。
coordinates里的那些数组,其实就是描点连线。第一个数组里的每一个小数组,代表一条闭合的折线(多边形)。你看最后那个点和第一个点是一样的,对吧?这就是为了把线”封”起来,形成一个封闭的区域。
我一开始也搞不清楚为什么有时候是Polygon有时候又是MultiPolygon。其实很简单:Polygon就是单个地块,MultiPolygon就是好几块不相连的地。比如海南省,它除了海南岛本身,还有一堆小岛礁,这时候就得用MultiPolygon了。
去哪找靠谱的GeoJSON数据
这问题问得太好了,因为我当年就是在这里栽了最大的跟头。你随便在网上搜”中国地图GeoJSON”,下载下来一跑,发现省份边界对不上,或者有些地方缺了一块,那种感觉真的想把电脑砸了。
我现在的做法是这样的:
首选方案:阿里云DataV.GeoAtlas
这个工具真的绝了,界面友好,数据质量高。你进去之后可以选择国家、省份、城市,然后直接下载对应级别的GeoJSON。更重要的是,它还帮你处理好了行政区划代码(adcode),这个代码在后续绑定数据的时候超级好用。
备选方案:自然地球(Natural Earth)
如果你需要全球范围的数据,这个网站的分辨率选择比较多,从1:10m到1:110m都有。不过它的行政区划边界不如阿里云的精细,而且有些地方国界线有争议,你得自己判断用哪条线。
高阶玩家:OpenStreetMap导出
如果你需要某个特定乡镇的精细边界,可以去OpenStreetMap上找到对应区域,然后导出GeoJSON。不过这个得会一点OSM的使用技巧,而且数据清洗的工作量比较大。
我这里整理了一个我自己常用的数据源对比表:
| 数据源 | 精度 | 覆盖范围 | 更新频率 | 适用场景 |
|---|---|---|---|---|
| 阿里云DataV | 高 | 中国 | 实时更新 | 国内项目首选 |
| 自然地球 | 中 | 全球 | 季度更新 | 国际地图展示 |
| OpenStreetMap | 超高 | 局部区域 | 实时众包 | 乡镇级精细地图 |
| 各省统计局 | 高 | 特定省份 | 年度更新 | 政务项目 |
从零开始:搭建一个最简单的地图页面
好,数据搞到了,咱们现在就来写代码。别担心,我保证这次不扔一大段代码出来吓你,咱们一步一步来。
首先,创建一个HTML文件,引入Echarts:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的第一张Echarts地图</title>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.map-container {
width: 90vw;
height: 80vh;
background: white;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
padding: 20px;
}
#mapChart {
width: 100%;
height: calc(100% - 40px);
}
</style>
</head>
<body>
<div class="map-container">
<div id="mapChart"></div>
</div>
<script>
// 第一步:初始化echarts实例
const chart = echarts.init(document.getElementById('mapChart'));
// 第二步:这里先放一个最简单的配置,后面我们会逐步填充
const option = {
title: {
text: '中国地图示例',
subtext: 'GeoJSON数据驱动',
left: 'center',
top: 20,
textStyle: {
fontSize: 24,
fontWeight: 'bold',
color: '#333'
},
subtextStyle: {
fontSize: 14,
color: '#666'
}
},
tooltip: {
trigger: 'item',
formatter: '{b}' // 显示区域名称
},
// 第三步:视觉映射,根据数值改变颜色
visualMap: {
min: 0,
max: 1000,
left: 'left',
top: 'bottom',
text: ['高', '低'],
calculable: true,
inRange: {
color: ['#e8f5e9', '#4caf50', '#2e7d32']
},
textStyle: {
color: '#333'
}
},
// 第四步:地图系列配置
series: [
{
name: '中国地图',
type: 'map',
map: 'china', // 这个名称后面会和注册的地图名称对应
roam: true, // 允许缩放和平移
zoom: 1.2,
label: {
show: true,
color: '#333',
fontSize: 10
},
emphasis: {
label: {
color: '#fff',
fontSize: 12,
fontWeight: 'bold'
},
itemStyle: {
areaColor: '#ff9800',
shadowBlur: 10,
shadowColor: 'rgba(0,0,0,0.5)'
}
},
select: {
disabled: true
}
}
]
};
chart.setOption(option);
// 响应式处理
window.addEventListener('resize', () => {
chart.resize();
});
</script>
</body>
</html>
这段代码跑起来之后,你会看到一个空白的地图区域,因为咱们还没注册地图数据呢。别急,这才是热身。
注册自定义地图:最关键的一步
现在咱们要把刚才下载的GeoJSON数据用起来。这一步叫registerMap,是整个流程的核心。
// 假设你已经把GeoJSON数据保存在一个变量里了
// 实际项目中,你可能会通过fetch异步获取
fetch('https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json')
.then(response => response.json())
.then(chinaGeoJSON => {
// 注册地图,第一个参数是地图名称,第二个是GeoJSON数据
echarts.registerMap('china', chinaGeoJSON);
// 更新配置,把series里的map改成我们注册的名称
chart.setOption({
series: [{
name: '中国地图',
type: 'map',
map: 'china', // 这里引用注册的名称
roam: true,
zoom: 1.2,
label: {
show: true,
color: '#333',
fontSize: 10
},
emphasis: {
label: {
color: '#fff',
fontSize: 12,
fontWeight: 'bold'
},
itemStyle: {
areaColor: '#ff9800',
shadowBlur: 10,
shadowColor: 'rgba(0,0,0,0.5)'
}
}
}]
});
})
.catch(error => {
console.error('地图数据加载失败:', error);
});
注意看这里,echarts.registerMap('china', chinaGeoJSON),第一个参数'china'就是你后面在series里引用的名称。你可以把它叫成任何你喜欢的名字,比如'myMap'、'provinceMap',只要保持一致就行。
加上数据:让地图”活”起来
光有边界有啥意思?咱们得让地图显示真实数据。比如,显示各省的GDP、人口、或者任何你想展示的信息。
// 模拟各省数据
const mapData = [
{ name: '广东省', value: 124369 },
{ name: '江苏省', value: 116364 },
{ name: '山东省', value: 83095 },
{ name: '浙江省', value: 77715 },
{ name: '河南省', value: 58887 },
{ name: '四川省', value: 53851 },
{ name: '湖北省', value: 45828 },
{ name: '湖南省', value: 46063 },
{ name: '安徽省', value: 42959 },
{ name: '福建省', value: 47625 },
// ... 其他省份
];
// 更新series配置
chart.setOption({
series: [{
name: '各省GDP(亿元)',
type: 'map',
map: 'china',
roam: true,
zoom: 1.2,
data: mapData, // 关键:把数据传进来
label: {
show: true,
color: '#333',
fontSize: 10,
formatter: function(params) {
// 自定义标签显示,只显示名称,不显示数值
return params.name;
}
},
emphasis: {
label: {
color: '#fff',
fontSize: 12,
fontWeight: 'bold'
},
itemStyle: {
areaColor: '#ff9800',
shadowBlur: 10,
shadowColor: 'rgba(0,0,0,0.5)'
}
}
}],
visualMap: {
min: 0,
max: 130000,
left: 'left',
top: 'bottom',
text: ['高GDP', '低GDP'],
calculable: true,
inRange: {
color: ['#fff9c4', '#ffee58', '#fbc02d', '#f57f17', '#e65100', '#bf360c']
},
textStyle: { color: '#333' }
}
});
跑起来之后,你会看到中国地图上,各省份根据GDP数值显示不同的颜色,深红色的是GDP高的省份,淡黄色的则是较低的。点击某个省份,还会高亮显示,这就是交互的魅力。
省份级别地图:只画一个省
有时候你不需要全国地图,只需要某个省的精细地图。比如,你想研究广东省内各个城市的分布情况。这时候,你需要下载广东省的GeoJSON,然后注册成新的地图名称。
fetch('https://geo.datav.aliyun.com/areas_v3/bound/440000_full.json')
.then(response => response.json())
.then(guangdongGeoJSON => {
echarts.registerMap('guangdong', guangdongGeoJSON);
// 广东省城市数据
const cityData = [
{ name: '广州市', value: 18807 },
{ name: '深圳市', value: 32387 },
{ name: '佛山市', value: 11936 },
{ name: '东莞市', value: 11446 },
{ name: '中山市', value: 4411 },
{ name: '江门市', value: 4752 },
{ name: '湛江市', value: 4283 },
{ name: '惠州市', value: 5309 },
{ name: '珠海市', value: 4304 },
{ name: '汕头市', value: 3625 },
];
chart.setOption({
series: [{
name: '广东省城市GDP',
type: 'map',
map: 'guangdong', // 引用我们注册的广东省地图
roam: true,
zoom: 1.1,
data: cityData,
label: {
show: true,
color: '#333',
fontSize: 9,
formatter: '{b}'
},
emphasis: {
label: { color: '#fff', fontSize: 11 },
itemStyle: {
areaColor: '#2196f3',
shadowBlur: 8,
shadowColor: 'rgba(0,0,0,0.3)'
}
}
}],
visualMap: {
min: 0,
max: 35000,
left: 'left',
top: 'bottom',
text: ['高', '低'],
calculable: true,
inRange: {
color: ['#e3f2fd', '#2196f3', '#0d47a1']
}
}
});
});
这里有个小细节要注意:GeoJSON里的properties.name必须和你的数据里的name完全一致,包括空格和标点符号。不然Echarts匹配不上,数据就显示不出来了。
县级地图:精细到乡镇级别
现在咱们玩点刺激的——县级地图。这个精度要求更高,数据量也更大,但效果真的超棒。
”`javascript fetch(’https://geo.datav.aliyun.com/areas_v3/bound/440300_full.json’)
.then(response => response.json())
.then(shenzhenGeoJSON => {
echarts.registerMap('shenzhen', shenzhenGeoJSON);
// 深圳各区数据(示例)
const districtData = [
{ name: '福田区', value: 5508 },
{ name: '南山区', value: 5769 },
{ name: '罗湖区', value: 3582 },
{ name: '宝安区', value: 7158 },
{ name: '龙岗区', value: 6151 },
{ name: '盐田区', value: 402 },
{ name: '龙华区', value: 4370 },
{ name: '坪山区', value: 1428 },
{ name: '光明区', value: 1789 },
];
chart.setOption({
title: {
text: '深圳市各区GDP分布',
left: 'center',
top: 10,
textStyle: { fontSize: 18, color: '#333' }
},
series: [{
name: '深圳市',
type: 'map',
map: 'shenzhen',
roam: true,
zoom: 1.3,
data: districtData,
label: {
