说实话,第一次用 ECharts 做地图的时候,我也曾对着屏幕上那团乱糟糟的线条怀疑人生。为什么省份不显示?为什么颜色对不上?为什么鼠标悬停没反应?
今天我们就把这些坑一个个填平。我不讲那些枯燥的官方文档翻译,而是用实战的方式,带你从解析 GeoJSON 开始,一步步画出那种让产品经理点头、老板鼓掌的专业数据地图。
为什么要自己搞懂 GeoJSON?
很多人直接去网上下载一个现成的地图 JSON,然后粘贴代码,完事。但当你需要定制——比如只展示某个省份、修改边界样式、或者处理动态数据时,你就傻眼了。
GeoJSON 本质上就是一个描述地理形状的 JavaScript 对象。它看起来有点吓人,但其实逻辑很简单。我们拿浙江省当例子,它不是简单的一个多边形,而是由“外环”和几个“内环”(比如海岛)组成的。
在 ECharts 里,我们需要把 GeoJSON 注册进去,才能使用。这个过程就像是你去健身房办卡,你得先有“会员资格”,才能进场地运动。
// 这是一个极简的 GeoJSON 结构示意,现实中浙江省的数据有几千个坐标点
const zhejiangGeoJSON = {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: { name: "浙江省" },
geometry: {
type: "Polygon",
coordinates: [
// 这里是经纬度坐标数组,第一层是外边界,后面的是内边界(湖泊或岛屿)
[[118.0, 30.0], [120.0, 30.0], [120.0, 28.0], [118.0, 28.0], [118.0, 30.0]]
]
}
}
]
};
别被这么多括号吓到,你只需要记住:一个 Polygon(多边形)就是由一组封闭的坐标点连成的面。ECharts 会把这些点连起来,填上颜色,就形成了我们看到的地图块。
第一步:加载地图,别再报错了
最常见的错误就是:代码写得没问题,但地图上什么都没有,或者报 undefined。
这通常是因为地图数据没加载对。ECharts 官方现在不直接内置中国地图了,你需要自己去下载对应的 GeoJSON 文件。
你可以从 阿里云 DataV 地理平台 下载高精度的中国地图 GeoJSON。下载后,你会得到一个 .json 文件。
关键点来了: 你不能直接把这个 JSON 文件扔给 ECharts 就用。你需要用 fetch 或者 axios 把它请求回来,然后用 echarts.registerMap 注册它。
// 假设你已经下载了 china.json
// 在实际项目中,你通常会把文件放在 public 或 static 目录下
echarts.registerMap('china', chinaGeoJSON);
// 然后在 option 中使用
const option = {
series: [{
type: 'map',
map: 'china', // 这里必须和 registerMap 的第一个参数一致
roam: true, // 允许缩放和平移
zoom: 1.2,
label: {
show: true,
color: '#333'
},
itemStyle: {
areaColor: '#eee',
borderColor: '#999'
},
emphasis: {
label: { color: '#d35400', fontSize: 14 },
itemStyle: { areaColor: '#f39c12' }
}
}]
};
避坑指南:
- 名字要一致:
registerMap('china', ...)里的'china'和map: 'china'里的'china'必须一模一样,大小写也要对。 - 异步加载问题:如果你在 Vue 或 React 项目里,确保地图数据加载完成后再渲染图表。否则你会看到一个空白的 div。可以用
setTimeout兜底,或者用async/await等待数据回来。
第二步:给省份上色,让数据说话
地图只是个骨架,数据才是灵魂。我们要做的是地图散文(Map Series),根据每个省份的数值(比如 GDP、人口、销售额)来改变颜色深浅。
这里有个新手最容易踩的坑:数据映射逻辑搞反了。
你是想让数值越大颜色越深,还是越浅?是连续渐变,还是分段色块?
我们用销售数据来举个例子。假设我们有三个省份:广东、浙江、江苏。
// 模拟后台返回的数据
const salesData = [
{ name: '广东省', value: 15000000 },
{ name: '浙江省', value: 12000000 },
{ name: '江苏省', value: 11000000 },
{ name: '北京市', value: 8000000 },
{ name: '上海市', value: 7500000 }
];
// 注意:其他未列出数据的省份,value 默认为 0 或 null
在 ECharts 中,我们使用 visualMap 组件来控制颜色映射。这是让地图看起来“专业”的关键神器。
const option = {
// visualMap 让地图拥有自动着色能力
visualMap: {
min: 0,
max: 20000000, // 根据你的最大数据调整
left: 'left',
top: 'bottom',
text: ['高', '低'],
calculable: true,
inRange: {
// 颜色从浅蓝到深蓝的渐变
color: ['#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695']
},
textStyle: {
color: '#333'
}
},
series: [
{
name: '销售额',
type: 'map',
map: 'china',
roam: true,
zoom: 1.2,
// 关键:把数据赋值给 data 属性
data: salesData,
label: {
show: true,
fontSize: 10,
color: '#666'
},
emphasis: {
label: { show: true, fontSize: 12, fontWeight: 'bold' },
itemStyle: {
areaColor: '#f39c12', // 悬停时的颜色
shadowBlur: 10,
shadowColor: 'rgba(0,0,0,0.3)'
}
},
// 不显示数据的省份设为灰色,突出有数据的省份
itemStyle: {
areaColor: '#f0f0f0',
borderColor: '#fff',
borderWidth: 1
}
}
]
};
为什么这样看起来更专业?
- 视觉层次:通过
visualMap,用户一眼就能看出哪些区域是热点。 - 交互反馈:
emphasis配置让鼠标悬停时有高亮和阴影,给用户明确的反馈。 - 细节处理:给未标注数据的省份设置一个中性色(如灰色),避免它们抢眼,同时让地图背景完整。
第三步:处理边界和样式,告别“廉价感”
很多新手做出来的地图,边界线粗黑,颜色突兀,看起来像小学作业。怎么改?
1. 调整边界线宽和颜色
默认情况下,ECharts 地图的边界线是黑色的,而且有点粗。我们需要把它调细,颜色调淡,这样地图会更精致。
itemStyle: {
areaColor: '#f4f4f4', // 背景色
borderColor: '#dcdcdc', // 边界线颜色,浅灰色
borderWidth: 0.5, // 边界线宽度,0.5 足够细且清晰
shadowColor: 'rgba(0, 0, 0, 0.1)', // 轻微阴影,增加立体感
shadowBlur: 5
}
2. 字体优化
默认的字体可能太小或者颜色太深。我们可以根据背景色调整字体颜色,确保可读性。
label: {
show: true,
fontSize: 9,
color: '#555', // 深灰色,比纯黑柔和
fontWeight: 'normal'
}
3. 添加点击事件,实现钻取
专业地图不只是看,还要能交互。比如点击“浙江省”,进入显示浙江省下辖的杭州、宁波等城市地图。
这需要两层地图数据:中国地图 GeoJSON 和 浙江省地图 GeoJSON。
// 假设已经注册了 zhejiang 地图
echarts.registerMap('zhejiang', zhejiangGeoJSON);
// 点击事件监听
myChart.on('click', function(params) {
// params.name 就是点击的省份名字
if (params.seriesName === 'china') {
// 如果点击的是省份,切换到该省地图
// 这里可以根据 params.name 动态加载对应的 GeoJSON 并重新 setOption
option.series[0].map = params.name; // 简单示意,实际需处理名称映射
option.series[0].data = getCityData(params.name); // 获取该省的城市数据
myChart.setOption(option, true); // true 表示不合并,完全重绘
}
});
注意:地图钻取的核心是数据替换。你需要为每个省份准备对应的下级地图数据和数据集合。这在大数据量时会有性能问题,所以建议分页加载或按需请求。
第四步:常见坑点排查清单
如果你按照上面的步骤做了,但还是有问题,请对照以下清单检查:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 地图不显示,只有空白 | GeoJSON 未正确注册 | 检查 registerMap 的回调,确保 JSON 解析成功 |
| 省份名字乱码或显示错误 | GeoJSON 中 properties.name 字段名不匹配 |
检查 GeoJSON 结构,确保有 name 字段,且在 series.name 中对应 |
| 颜色没有变化 | visualMap 的 min/max 设置不当 |
调整 min 和 max,确保覆盖数据范围 |
| 点击事件不生效 | 事件监听时机不对 | 在 setOption 之后或 chart.on 绑定事件 |
| 移动端显示模糊 | 地图分辨率太低 | 使用高分辨率的 GeoJSON,或在 CSS 中设置 width: 100% 而非固定像素 |
第五步:让地图更有故事感
最后,我们来加点“料”,让你的地图不仅仅是一张图,而是一个能讲故事的数据可视化作品。
1. 添加散点,标注重点区域
除了色块,我们还可以在地图上添加散点,标注具体的城市或地点。比如,在浙江省地图上,用红点标出 GDP 最高的几个城市。
series: [
{
type: 'map',
map: 'china',
// ... 地图配置
},
{
type: 'effectScatter', // 带涟漪效果的散点
coordinateSystem: 'geo',
data: convertData([ // 将经纬度转换为屏幕坐标
{ name: '杭州', value: [120.15, 30.28, 15000000] },
{ name: '宁波', value: [121.55, 29.87, 12000000] }
]),
symbolSize: 10,
showEffectOn: 'render',
rippleEffect: {
brushType: 'stroke'
},
label: {
show: true,
formatter: '{b}',
position: 'right',
color: '#c0392b'
},
itemStyle: {
color: '#c0392b'
},
emphasis: {
scale: true
}
}
]
effectScatter 是 ECharts 的一个亮点,它在散点上添加了动态的涟漪效果,让重要数据点瞬间抓住用户的眼球。
2. 添加工具提示,展示详细信息
当鼠标悬停在某个省份上时,除了显示名称,我们还可以显示更详细的信息,比如具体数值、增长率、趋势图等。
series: [{
type: 'map',
// ...
tooltip: {
trigger: 'item',
formatter: function(params) {
// params 是当前悬停的地图项
return `<div style="padding: 10px; font-size: 14px;">
<strong>${params.name}</strong><br/>
销售额:<span style="color: #e74c3c; font-weight: bold;">${(params.value / 10000).toFixed(2)} 万元</span><br/>
增长率:<span style="color: #27ae60;">+5.2%</span>
</div>`;
}
}
}]
通过自定义 formatter,你可以完全控制提示框的内容和样式,甚至可以在里面嵌入一个迷你柱状图,让信息密度更高。
结语:从“能用”到“好用”
画一张 ECharts 地图并不难,难的是让它好用、好看、好理解。
我们从 GeoJSON 的解析开始,解决了注册和加载的问题;通过 visualMap 实现了数据的直观映射;调整样式去除了“廉价感”;最后通过散点和自定义提示框增加了交互性和信息密度。
记住,数据可视化的核心不是炫技,而是清晰地传达信息。每一行代码、每一个样式调整,都应该服务于这个目标。
下次当你再打开 ECharts 官网,看到那些炫酷的地图案例时,不要只是惊叹。试着去拆解它:它是用什么地图数据?颜色是怎么映射的?交互逻辑是怎样的?然后,动手把它复刻出来,再加上你自己的创意。
这才是从“会用”到“精通”的必经之路。去吧,画出属于你的专业数据地图!
