做地图可视化,尤其是用 ECharts 做中国各省份的分级渲染,听起来挺高大上,实际上坑能把你埋了。我见过太多开发者,GeoJSON 格式对不上、颜色映射乱成一团、边界线消失得无影无踪,最后只能对着控制台报错发呆。今天咱们就把这套流程从头到尾捋一遍,不整那些虚头巴脑的理论,直接上干货,让你一次性把地图搞定。
数据来源:别去官网下,去这里
先说 GeoJSON 从哪来。很多人第一反应是去 GADM 或者自然地球官网下载,结果导回来的数据要么坐标系是 WGS84(EPSG:4326),要么分辨率太高,几十万个点,加载起来页面直接卡死。还有人下了个“中国地图”,结果南海诸岛是散落的岛礁,没有完整海域边界,地图上看着怪怪的。
我推荐的源头是阿里云 DataV.GeoAtlas。这个工具稳定、更新快,支持自定义分辨率,而且下载下来的 GeoJSON 可以直接在 ECharts 里用。你去官网选“中国”→“省份”,分辨率选中等就行,一般 0.5 到 1 之间最合适——太小边界模糊,太大数据量爆炸。下载完之后,你会得到一个 .json 文件,里面包含了所有省份的多边形坐标数据。
拿这个文件举个例子,结构大概长这样:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "新疆维吾尔自治区",
"cp": [85.1922, 41.0498],
"childName": "新疆"
},
"geometry": {
"type": "Polygon",
"coordinates": [[[73.5, 39.5], [74.0, 39.6], ...]]
}
},
{
"type": "Feature",
"properties": {
"name": "广东省",
"cp": [113.5, 22.8],
"childName": "广东"
},
"geometry": {
"type": "Polygon",
"coordinates": [[[109.5, 20.5], [110.0, 20.6], ...]]
}
}
]
}
注意看 properties 里的 name 和 childName,这两个字段至关重要。ECharts 注册地图时,需要靠它们来匹配数据。如果名称对不上,地图渲染出来就是一片空白,或者某些省份没有颜色。
数据清洗:把“脏数据”变成“干净数据”
你下载的 GeoJSON 有时候并不完美。比如,有些省份可能缺少南海诸岛的子区域,或者某些城市的边界数据有重叠、自相交。这时候就需要清洗。
我写过一个清洗脚本,用 Python 的 geojson 和 shapely 库来处理。核心思路是:
- 读取 GeoJSON
- 检查每个 Feature 的 geometry 是否合法
- 修复多边形自相交
- 合并破碎的多边形
- 输出清洗后的 GeoJSON
import geojson
from shapely.geometry import Polygon, shape, mapping
from shapely.validation import make_valid
def clean_geojson(input_path, output_path):
with open(input_path, 'r', encoding='utf-8') as f:
data = geojson.load(f)
cleaned_features = []
for feature in data['features']:
geom = shape(feature['geometry'])
# 修复无效几何
if not geom.is_valid:
geom = make_valid(geom)
# 如果是 MultiPolygon,转成 Polygon 列表
if geom.geom_type == 'MultiPolygon':
for poly in geom.geoms:
cleaned_features.append({
'type': 'Feature',
'properties': feature['properties'],
'geometry': mapping(poly)
})
elif geom.geom_type == 'Polygon':
cleaned_features.append({
'type': 'Feature',
'properties': feature['properties'],
'geometry': mapping(geom)
})
clean_data = {
'type': 'FeatureCollection',
'features': cleaned_features
}
with open(output_path, 'w', encoding='utf-8') as f:
geojson.dump(clean_data, f, ensure_ascii=False, indent=2)
# 使用示例
clean_geojson('china_provinces.json', 'china_provinces_clean.json')
这段代码能帮你把那些“奇奇怪怪”的几何体修好。特别是 make_valid,它能自动处理自相交、退化多边形等问题。清洗完的文件,你可以用在线的 geojson.io 工具打开预览,确认每个省份的边界都完整、正确。
ECharts 注册地图:最关键的一步
清洗好的 GeoJSON,接下来要注册到 ECharts 里。这一步有个大坑:注册时的名称必须和 GeoJSON 里的 properties.name 完全一致,包括全角半角、空格、标点符号。
比如,GeoJSON 里写的是 "name": "新疆维吾尔自治区",你注册时写成 "Xinjiang",那就算数据匹配上了,地图上也显示不出来。我曾经因为少了一个“族”字,调试了两个小时,最后才发现是名称不匹配。
注册代码很简单:
// 假设你已经用 fetch 加载了清洗后的 GeoJSON
fetch('china_provinces_clean.json')
.then(response => response.json())
.then(geoJson => {
// 注册地图
echarts.registerMap('china', geoJson);
// 创建图表
const chart = echarts.init(document.getElementById('map-container'));
chart.setOption(option);
});
注意,echarts.registerMap 的第一个参数 'china' 是地图名称,后面你在 option 里要用这个名字来引用。第二个参数就是 GeoJSON 对象。这里有个细节:如果你下载的是全国地图,但只想显示部分省份,可以在 GeoJSON 里过滤掉不需要的 Feature,然后再注册。
颜色分级渲染:让地图“说话”
数据准备好,地图注册好,接下来就是最有趣的部分:给每个省份上色。这就是所谓的“分级渲染”,通常用来展示数值型数据,比如各省的 GDP、人口、碳排放量等。
ECharts 的 visualMap 组件就是干这个的。它可以根据数据值的大小,自动映射到不同的颜色。
先假设你有一份数据:
const data = [
{ name: '新疆维吾尔自治区', value: 17000 },
{ name: '广东', value: 124300 },
{ name: '江苏', value: 116400 },
{ name: '山东', value: 92600 },
// ... 其他省份
];
然后配置 visualMap:
const option = {
tooltip: {
trigger: 'item',
formatter: '{b}<br/>GDP: {c} 亿元'
},
visualMap: {
min: 0,
max: 130000,
left: 'left',
top: 'bottom',
text: ['高', '低'],
calculable: true,
inRange: {
color: ['#ffffcc', '#c7e9b4', '#7fcdbb', '#41b6c4', '#225ea8']
},
textStyle: {
color: '#333'
}
},
series: [{
name: 'GDP分布',
type: 'map',
map: 'china',
roam: true,
zoom: 1.2,
label: {
show: true,
color: '#333',
fontSize: 10
},
emphasis: {
label: {
fontSize: 12,
color: '#d4a017'
},
itemStyle: {
areaColor: '#ffeb3b'
}
},
data: data
}]
};
运行起来之后,你会发现颜色是根据 data 里的 value 自动分配的。最小值对应 inRange.color 的第一个颜色,最大值对应最后一个颜色,中间的值线性插值。
这里有个坑:如果你的数据里没有包含某个省份,那这个省份会显示为灰色,也就是 ECharts 默认的“无数据”颜色。所以,确保你的数据数组里包含所有你想展示的省份,哪怕有些省份的值是 0。
常见踩坑总结
坐标系问题:GeoJSON 默认是 WGS84,ECharts 支持这个坐标系,但如果你导出的数据是 Web Mercator(EPSG:3857),那地图位置会偏移。检查一下 GeoJSON 的
crs字段,如果没有,默认就是 WGS84,没问题。名称匹配:再强调一遍,
properties.name必须和data里的name完全一致。建议用代码自动化匹配,不要手动复制粘贴。南海诸岛缺失:很多 GeoJSON 数据源不包含南海诸岛。如果你需要在地图上显示九段线,得额外添加南海诸岛的 GeoJSON 数据,并且调整地图的
left、top、width、height参数,给南海小图留出空间。性能问题:如果 GeoJSON 数据量太大(比如每个省份有上万个坐标点),渲染会卡顿。这时候可以用 Douglas-Peucker 算法简化多边形,降低坐标点数量。我一般控制在每个省份 500-1000 个点以内,视觉效果差不多,但性能提升明显。
交互体验:
roam: true允许缩放和平移,zoom可以设置初始缩放级别。如果地图默认太小,用户得手动放大才能看清省份边界。建议初始zoom设为 1.1 到 1.3 之间。颜色过渡生硬:
inRange.color数组如果只有两个颜色,过渡会很突兀。建议用 5 到 7 个颜色,形成平滑的渐变。可以用在线工具生成配色方案,比如 colorbrewer2.org。
给小朋友的通俗解释
想象一下,你有一张中国地图的拼图,但是拼图块上没有画颜色。现在你要根据每个省份的“温度”来涂色:温度高的涂红色,温度低的涂蓝色,中间的涂绿色。ECharts 就是一个自动涂色的机器,你告诉它每个省份的温度是多少,它就帮你把颜色涂好。但是,你得保证拼图块的名字和温度表上的名字一模一样,不然机器就找不到该涂哪个块。
结语
从 GeoJSON 清洗到 ECharts 渲染,这条路虽然有点坑,但走通之后就是一马平川。关键点就三个:数据要干净、名称要匹配、配置要合理。希望这篇实战指南能帮你少走弯路,早日做出漂亮的地图可视化。如果你在实际操作中遇到其他问题,欢迎随时交流,咱们一起把地图做得更漂亮。
