嘿,朋友。如果你正盯着屏幕发呆,脑子里转着“Echarts地图怎么自己画”、“GeoJSON是个啥”、“为啥我的省份颜色出不来”这些念头,那咱俩是同道中人。我当年刚开始折腾这个的时候,也是从一堆报错和灰蒙蒙的地图里爬出来的。
今天我不跟你讲那些枯燥的定义,咱们直接上手。我会把这一路走来的坑、弯路、还有那些让我拍大腿的“原来如此”的细节,掰开了揉碎了讲给你听。咱们目标很明确:拿到GeoJSON -> 注册到Echarts -> 成功着色 -> 顺便加点数据让它活起来。
准备好了吗?咱们开始。
第一步:为什么是GeoJSON?它到底是什么?
别被名字吓到。GeoJSON只是一种格式,用来描述地球上的形状。
想象一下,你有一张中国地图的轮廓图。这张图是怎么存在的?在Echarts里,它就是一个巨大的JSON对象。这个对象里定义了:
- 每个省份是什么形状(由无数个坐标点连线而成)
- 每个省份叫什么名字(比如“广东省”)
- 每个省份在地图上的大致位置
核心概念:Echarts不认识“中国地图”这个词,它只认识标准的GeoJSON数据。所以,获取正确、标准的GeoJSON文件,是成功的第一步,也是最重要的一步。
去哪里找GeoJSON?
网上资源挺多,但良莠不齐。我推荐几个靠谱的地方:
- 阿里云DataV.GeoAtlas:这个最常用,界面友好,支持按省份、地市下载。
- 高德地图开放平台:也有地图数据下载。
- GitHub:搜“china geojson”、“world geojson”,一堆开源项目。
避坑重点:
- 坐标系问题:这是新手最大的坑!GeoJSON通常使用WGS84坐标系(经纬度)。但有时候你会听到“GCJ-02”(火星坐标系)。Echarts的
geo组件默认支持WGS84。如果你从某些国内地图服务直接拿数据,一定要确认坐标系。如果坐标系不对,你的地图可能会偏移,或者完全加载不出来。 - 数据完整性:确保下载的是整个中国的GeoJSON,而不是某个省单独的。否则后续做全国地图时,别的省份会缺失。
第二步:手把手获取并理解GeoJSON
咱就拿阿里云DataV为例,实际操作一下。
- 打开 DataV.GeoAtlas。
- 在地图上点击你想下载的省份,或者直接在左侧选择“全国”、“广东省”等。
- 点击“查看数据”或“下载”,你会得到一个
.json文件。 - 用文本编辑器(VSCode, Sublime Text等)打开它。
别被吓到,看着复杂,其实结构很清晰。 简单举个例子:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"adcode": 440000, // 广东省的行政代码
"name": "广东省", // 省份名称
"center": [113.264385, 23.129162], // 中心点坐标
"childrenNum": 21,
"level": "province",
"subFeatures": []
},
"geometry": {
"type": "Polygon",
"coordinates": [[[113.26, 23.12], [114.00, 23.50], ...]] // 具体的边界坐标点
}
},
{
"type": "Feature",
"properties": {
"adcode": 420000,
"name": "湖北省",
...
},
"geometry": { ... }
}
// 其他省份...
]
}
关键信息提取:
features数组里每个对象代表一个省份/地区。properties.name是省份显示的名称,这个名称将用于后续的数据映射,必须完全一致!properties.adcode是行政代码,有时候也会用来做数据关联。
实操建议:下载好后,把它放在你项目的静态资源目录下,比如 src/assets/china.json。这样浏览器就能通过 fetch 或 $.get 请求到它了。
第三步:Echarts注册自定义地图
这是最核心的代码环节。别急,我会一步步拆解。
首先,引入Echarts:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Echarts 自定义地图示例</title>
<!-- 引入 Echarts -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
</head>
<body>
<!-- 为 Echarts 准备一个定义了宽高的 DOM -->
<div id="main" style="width: 100%; height: 600px;"></div>
<script type="text/javascript">
// 你的代码将写在这里
</script>
</body>
</html>
第一步:获取GeoJSON数据
// 使用 fetch 获取 GeoJSON 数据
fetch('https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json') // 这是全国地图的阿里云官方链接
.then(response => response.json())
.then(geoJson => {
// 第二步:注册地图
echarts.registerMap('china', geoJson);
// 第三步:初始化 Echarts 实例
initChart(geoJson);
})
.catch(error => {
console.error('获取 GeoJSON 数据失败:', error);
});
注意:我用的是阿里云的公开链接,你也可以下载后本地访问。echarts.registerMap('china', geoJson) 是告诉Echarts:“嘿,这个叫 ‘china’ 的地图数据,长这样,以后用这个名字就能调用它。”
第二步:配置Echarts选项
function initChart(geoJson) {
const dom = document.getElementById('main');
const myChart = echarts.init(dom);
// 准备数据,假设我们有一些省份的销售数据
const data = [
{ name: '广东省', value: 1000 },
{ name: '湖北省', value: 800 },
{ name: '浙江省', value: 900 },
{ name: '北京市', value: 1200 },
{ name: '上海市', value: 1100 }
];
const option = {
title: {
text: '中国省份数据分布图',
left: 'center'
},
// tooltip 鼠标悬浮提示
tooltip: {
trigger: 'item',
formatter: '{b}<br/>数值: {c}' // {b}是省份名, {c}是数值
},
// 核心配置项:visualMap 视觉映射组件
visualMap: {
min: 0,
max: 1500,
left: 'left',
top: 'bottom',
text: ['高', '低'],
calculable: true,
inRange: {
color: ['lightblue', 'blue', 'darkblue'] // 颜色渐变
},
seriesIndex: 0 // 指定第一个系列
},
// geo 组件,用于地图投影
geo: {
map: 'china', // 对应 registerMap 时的名字
roam: true, // 允许缩放和平移
zoom: 1.2, // 初始缩放
label: {
show: true, // 显示省份名称
color: '#333'
},
emphasis: { // 高亮样式
label: {
color: '#fff'
},
itemStyle: {
areaColor: '#f39c12' // 鼠标悬停颜色
}
},
select: { // 选中样式
label: {
color: '#fff'
},
itemStyle: {
areaColor: '#e74c3c'
}
}
},
// 系列配置
series: [
{
name: '中国地图',
type: 'map',
map: 'china', // 再次指定地图
geoIndex: 0, // 关联到 geo 组件,避免重复配置
aspectScale: 0.75, // 地图长宽比调整
data: data, // 关联数据
itemStyle: {
areaColor: '#eee',
borderColor: '#333' // 边框颜色
}
}
]
};
myChart.setOption(option);
// 响应式调整
window.addEventListener('resize', () => {
myChart.resize();
});
}
第四步:深度解析关键配置与避坑指南
上面代码跑起来,你应该能看到一张中国地图,部分省份有颜色,并且能交互。但细节里全是坑,我来一一拆解。
1. geo 和 series.map 的关系
这是最容易混淆的地方。
geo组件定义了地图的投影、显示样式、交互行为(比如缩放、平移、高亮效果)。series里的map类型系列,则负责展示数据和绑定数据。
最佳实践:通常我们在 series 里设置 geoIndex: 0,让它复用 geo 的配置。这样不用写两遍相同的地图配置,代码更简洁,也避免不一致。
避坑:如果你同时配置了 geo 和 series.map 里的 itemStyle,可能会产生冲突或无效。建议将通用的样式放在 geo 里,数据相关的样式(如颜色映射)由 visualMap 控制,或者在 series 里单独设置覆盖。
2. 数据名称必须完全匹配
看这一步的代码:
const data = [
{ name: '广东省', value: 1000 }, // 这里 name 必须和 GeoJSON 里 properties.name 完全一致
// ...
];
如果你写的 name: '广东',而GeoJSON里是 name: '广东省',那这条数据就匹配不上,这个省份就不会着色,会保持默认颜色(通常是 visualMap 范围外的颜色)。
解决方法:
- 仔细核对GeoJSON里的
properties.name。 - 可以在浏览器控制台打印出GeoJSON里的所有省份名称,对照着填数据。
- 或者,用
adcode来关联数据,如果GeoJSON里有adcode,你的数据也用adcode作为key,然后在series里配置nameMap或者直接通过data的name字段去匹配(Echarts内部会自动根据name匹配)。
3. 颜色映射 visualMap 的妙用
visualMap 是Echarts实现数据可视化的神器。它会根据你的数据范围,自动将数值映射到颜色。
visualMap: {
min: 0,
max: 1500,
inRange: {
color: ['lightblue', 'blue', 'darkblue'] // 从浅蓝到深蓝的渐变
},
// ...
}
避坑:
- 颜色数组长度:
color数组可以有2-3个颜色,Echarts会自动插值。如果超过3个,可能效果不如预期,建议2-3个。 - 超出范围的值:如果数据里有
value > max或value < min的,它们会被映射到颜色范围的边缘,或者根据outOfRange配置处理。 - 不显示颜色:如果某些省份没有数据,它们会显示
inRange.color的起始颜色,或者你可以设置outOfRange的color来区分无数据区域。
4. 地图显示不完整或偏移
如果你发现地图只显示了一部分,或者位置不对:
- 检查坐标系:确保GeoJSON是WGS84坐标系。如果不是,需要进行坐标转换。
- 检查
geo.roam:如果roam设置不当,可能会影响视图。 - 检查
geo.center和geo.zoom:初始的中心点和缩放比例可能没对准。可以通过调整这两个值来定位。 - 地图边界数据问题:有些GeoJSON数据可能不够精细,导致某些岛屿或边界显示异常。尝试换用更高分辨率的数据源。
5. 性能问题
如果地图数据非常大(比如包含所有地市的GeoJSON),可能会导致页面卡顿。
- 简化数据:对于不需要精细显示的区域,可以使用简化后的GeoJSON。
- 按需加载:只在用户展开某个省份时,才加载其下属地市的详细GeoJSON。
- Web Worker:对于超大JSON解析,可以考虑用Web Worker在后台线程处理,避免阻塞主线程。
第五步:进阶玩法 - 让地图更生动
基本地图搞定了,咱们加点料。
1. 添加散点图标记
比如,在广东省省会广州标出一个点。
series: [
{
// 地图系列
type: 'map',
map: 'china',
data: data
},
{
// 散点系列
type: 'effectScatter',
coordinateSystem: 'geo', // 使用 geo 坐标系
data: convertData([ // 将经纬度数据转换为GeoJSON格式的点
{ name: '广州', value: [113.26, 23.12, 100] }
]),
symbolSize: 15,
rippleEffect: {
brushType: 'stroke'
},
label: {
show: true,
formatter: '{b}',
position: 'right',
color: '#333'
}
}
]
// 辅助函数:转换数据格式
function convertData(data) {
// 这里需要根据你的数据源进行调整
// 假设你有一个从后端获取的包含经纬度的数据
// 简单示例:
return data.map(item => {
return {
name: item.name,
value: [item.lng, item.lat, item.value], // lng, lat, value
itemStyle: {
color: '#e74c3c'
}
};
});
}
2. 添加流线图
模拟数据从北京流向广东。
series: [
// 地图
{ type: 'map', map: 'china', data: data },
// 线系列
{
type: 'lines',
coordinateSystem: 'geo',
polyline: false,
data: [
{
fromName: '北京',
toName: '广东',
coords: [
[116.407526, 39.90403], // 北京坐标
[113.264385, 23.129162] // 广东坐标
],
lineStyle: {
color: '#f39c12',
width: 2,
curveness: 0.2
},
effect: {
show: true,
period: 4,
trailLength: 0.1,
symbol: 'arrow',
symbolSize: 5
}
}
]
}
]
注意:流线图需要知道起点和终点的经纬度。你可以从GeoJSON的 properties.center 获取大致中心点,或者使用具体的城市坐标。
3. 响应式与交互优化
// 监听窗口大小变化,调整图表大小
window.addEventListener('resize', () => {
myChart.resize();
});
// 点击省份进行高亮或跳转
myChart.on('click', function(params) {
if (params.componentType === 'series' && params.seriesType === 'map') {
console.log('点击了:', params.name);
// 可以触发路由跳转,或加载该省份的详情数据
}
});
第六步:常见问题排查清单
实在搞不定?对照这个清单检查:
- 控制台报错:F12打开开发者工具,看Console里有没有红色报错。最常见的错误是“找不到地图”、“数据格式错误”。
- 地图空白:
- GeoJSON加载失败?检查网络请求。
echarts.registerMap没执行?确保在获取数据后调用。geo.map名字和注册的名字不一致?
- 省份没颜色:
- 数据里的
name和GeoJSON里的properties.name是否完全一致?包括空格、标点。 visualMap的min/max是否覆盖了你的数据范围?- 数据是否成功传入
series.data?
- 数据里的
- 地图偏移:
- 确认GeoJSON坐标系。
- 检查
geo.center和geo.zoom。
- 性能卡顿:
- 数据量过大?尝试简化GeoJSON。
- 复杂图形?减少 `symbolSize
