说实话,刚开始玩ECharts自定义地图的时候,我也被那个GeoJson绕晕了好几次。明明代码没报错,地图上却啥也没有,或者颜色显示不对,那种感觉挺挫败的。但一旦你摸透了它的脾气,这事儿其实挺有意思的。今天咱们就把这个过程掰开揉碎了讲清楚,顺便把那些让人头秃的报错一起解决了。
为什么是GeoJson?
首先你得知道,ECharts自己的地图能力主要依赖GeoJson格式。这不是ECharts发明的,而是地理信息系统里的通用标准。简单来说,GeoJson就是一个JSON文件,里面存着一堆坐标点,把这些点连起来就能勾勒出某个地区的形状。
中国地图、世界地图这些常见的,ECharts官方都封装好了,你直接拿来用。但如果你想做某个具体城市、某个区县,甚至某个特定区域(比如珠江三角洲)的地图,就得自己找GeoJson数据源了。
第一步:搞定GeoJson数据源
这是最关键也是最容易卡壳的地方。很多人第一步就放弃了,因为数据难找。
去哪找靠谱的GeoJson?
- 国家地理信息公共服务平台(天地图):官方数据,最权威,但有时候访问速度一般。
- GSHHG(Global Self-consistent Hierarchical High-resolution Geography):全球海洋和陆地边界数据,适合做世界地图。
- 高德地图开放平台:国内数据比较准确,尤其是省市县边界。
- Natural Earth:国际通用的低分辨率地理数据,适合做世界地图或大范围区域。
- 各种GitHub开源项目:有人整理好的中国省份、城市GeoJson,搜索”china geojson”能找到不少。
比如,我上次需要一个深圳市的边界数据,就直接在高德开放平台申请了,下载下来就是个.json文件。
GeoJson长啥样?
别被格式吓到,你不需要手动写GeoJson。但得知道它的结构:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "广东省",
"adcode": 440000
},
"geometry": {
"type": "Polygon",
"coordinates": [[[112.5, 21.5], [113.5, 21.5], ...]]
}
}
]
}
核心就是features数组,每个元素代表一个区域,geometry里的coordinates是坐标点列表。properties里通常是名称、编码这些信息。
第二步:把GeoJson注册到ECharts
ECharts提供了一个registerMap方法,专门用来注册自定义地图。语法很简单:
echarts.registerMap('myMap', geoJsonData);
第一个参数是地图名称,以后你在option里引用这个名称就能用。第二个参数就是GeoJson数据。
完整示例代码
咱们写个完整的HTML文件,从加载数据到显示地图一步到位:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>自定义地图示例</title>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
</head>
<body>
<div id="main" style="width: 100%; height: 400px;"></div>
<script>
// 初始化ECharts实例
const myChart = echarts.init(document.getElementById('main'));
// 加载GeoJson数据
fetch('https://geo.datav.aliyun.com/area_v3/bound/440300_full.json')
.then(response => response.json())
.then(geoJson => {
// 注册地图
echarts.registerMap('shenzhen', geoJson);
// 配置项
const option = {
tooltip: {
trigger: 'item',
formatter: '{b}' // 显示区域名称
},
visualMap: {
min: 0,
max: 100,
left: 'left',
top: 'bottom',
text: ['高', '低'],
calculable: true,
inRange: {
color: ['#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027']
}
},
series: [{
name: '深圳市区域数据',
type: 'map',
map: 'shenzhen',
roam: true, // 允许缩放和平移
label: {
show: true,
fontSize: 10
},
emphasis: {
label: {
fontSize: 12
}
},
data: [
{name: '福田区', value: 80},
{name: '罗湖区', value: 60},
{name: '南山区', value: 90},
{name: '宝安区', value: 70},
{name: '龙岗区', value: 50}
]
}]
};
myChart.setOption(option);
})
.catch(error => {
console.error('加载GeoJson失败:', error);
alert('地图数据加载失败,请检查网络或数据源地址');
});
</script>
</body>
</html>
这段代码干了这几件事:
- 从阿里云DataV的GeoJson数据源拉取深圳市的边界数据
- 注册为名为’shenzhen’的自定义地图
- 配置一个地图系列,绑定数据
- 处理加载失败的情况
第三步:数据怎么填?
地图上显示什么颜色、什么数值,取决于series.data里的数据。每一条数据必须包含name,这个name要和GeoJson里properties.name匹配。
比如你GeoJson里有个区叫”福田区”,你的data里就得写{name: '福田区', value: 80}。名字对不上,那块区域就不会高亮,也不会显示数值。
数据匹配问题
有时候GeoJson里的名字和你手头数据里的名字不一样。比如数据里写的是”福田区”,但GeoJson里写的是”福田区(部分)”。这时候可以用setName方法或者在series里用data的name属性来映射。
更灵活的做法是,加载完GeoJson后,先打印出来看看features里的properties.name到底是啥,再对应填数据。
常见报错和排查方法
这里我把遇到的坑都列出来,帮你少走弯路。
报错1:地图不显示,空白一片
原因:
- GeoJson数据加载失败(网络问题、跨域、路径错误)
registerMap的地图名称和series里的map不一致- GeoJson格式不标准,ECharts解析失败
排查步骤:
- 打开浏览器控制台(F12),看Network标签,检查GeoJson的请求是否成功,返回状态是不是200。
- 在console里打印一下
geoJson,确认数据结构和上面说的一样,有features数组。 - 确认
echarts.registerMap('shenzhen', geoJson)和map: 'shenzhen'里的名字完全一致。
报错2:区域颜色不对,或者只有一块区域有颜色
原因:
series.data里的name和GeoJson里的properties.name不匹配visualMap配置有问题,比如min和max设置不对
排查步骤:
- 在console里打印GeoJson的features,看看每个区域的name到底是什么。
- 检查
series.data里的name是否完全一致,注意大小写、空格、特殊字符。 - 检查
visualMap的min和max是否合理,确保你的数据值在这个范围内。
报错3:点击区域没反应,tooltip不显示
原因:
- 没有配置
tooltip roam没有开启,导致缩放后点击区域偏移
排查步骤:
- 确保option里有
tooltip配置,并且trigger设为'item'。 - 开启
roam: true,允许用户缩放和平移地图。 - 检查浏览器控制台有没有JavaScript错误。
报错4:地图显示乱码,名字是乱码或者缺字
原因:
- GeoJson文件编码问题,不是UTF-8
- 页面HTML没有声明charset
排查步骤:
- 确认HTML文件开头有
<meta charset="utf-8">。 - 用文本编辑器打开GeoJson文件,确认编码是UTF-8。如果不是,转码再试。
- 如果是从API动态获取的,检查响应头里的Content-Type是否包含charset=utf-8。
报错5:浏览器控制台报”Cannot read properties of undefined”
原因:
- GeoJson数据加载后没有正确解析,可能是JSON格式错误
- 数据源返回的不是标准的GeoJson格式
排查步骤:
- 在
then里先打印typeof geoJson和geoJson.type,确认是不是FeatureCollection。 - 用在线GeoJson校验工具(比如geojson.io)验证你的数据文件是否合法。
- 如果数据是从多个来源拼凑的,确保拼接后的数据结构完整。
进阶技巧:怎么让地图更好看?
1. 地图样式自定义
你可以通过itemStyle来自定义地图块的颜色、边框等:
itemStyle: {
areaColor: '#eee',
borderColor: '#999',
borderWidth: 1
},
emphasis: {
itemStyle: {
areaColor: '#ffeb3b'
},
label: {
show: true,
color: '#333'
}
}
2. 叠加散点图或线图
地图不只是看区域,还能在上面叠加数据。比如用散点图表示各个区的商业中心:
series: [
{
type: 'map',
map: 'shenzhen',
data: [...],
itemStyle: {...}
},
{
type: 'effectScatter',
coordinateSystem: 'geo',
geoIndex: 0,
data: [
{name: '福田中心', value: [114.05, 22.53, 100]},
{name: '南山科技园', value: [113.95, 22.55, 80]}
]
}
]
注意,散点图要用coordinateSystem: 'geo',并且geoIndex指向地图系列的索引。
3. 加载多个区域的地图
如果你想在一个页面里放多个小地图,或者对比不同区域,可以注册多个地图,然后用grid或者layoutCenter、layoutSize来调整位置:
option = {
series: [
{
type: 'map',
map: 'china',
roam: true,
zoom: 1.2,
center: [105, 36]
},
{
type: 'map',
map: 'shenzhen',
roam: false,
zoom: 1,
center: [114.05, 22.53],
left: '60%',
top: '60%',
width: '30%',
height: '30%'
}
]
};
第二个地图通过left、top、width、height定位在右下角,不影响第一个地图的交互。
调试小技巧
- 永远先打印数据:遇到任何问题,先在console里把GeoJson和series.data打印出来,90%的问题都是数据对不上。
- 用最小化示例:先写个最简单的地图(只有map类型,没有visualMap、tooltip等),能显示出来再逐步加功能。
- 检查跨域:如果GeoJson是从其他域名加载的,确保服务器开启了CORS,或者用本地代理。开发环境可以直接用Live Server之类的工具本地运行。
- 浏览器开发者工具:Network标签看请求,Console标签看报错,Elements标签看DOM结构,这些都很有用。
总结
自定义地图的核心就三步:找数据、注册地图、配option。数据找对了,后面就是调样式和交互。大部分报错都是因为数据名不匹配或者格式不对,耐心对照一下就能解决。
ECharts的文档其实写得挺详细的,尤其是Series - Map这一节,建议遇到问题先翻翻文档,说不定就有答案。当然,如果文档里没写,或者写得不清楚,再来问我或者其他社区。
希望这篇教程能帮你搞定自定义地图。如果有具体的报错或者场景,可以贴出来,我帮你看看。做地图这事儿,试错几次就熟练了,别怕报错,报错信息是最好的老师。
