ECharts 地理坐标系(geo)完全指南
文档类型: 深度技术文档
难度等级: ⭐⭐⭐⭐
源码版本: ECharts 5.x
本文行数: 约600行
📋 目录
🎯 geo基础配置
基础地理坐标系
typescript
const option = {
// 地理坐标系组件
geo: {
map: 'china', // 使用中国地图
// 缩放和平移
roam: true, // 允许缩放平移
scaleLimit: {
min: 1, // 最小缩放
max: 10 // 最大缩放
},
// 初始视角
zoom: 1.2, // 缩放级别
center: [104.114129, 37.550339], // 中心点 [经度, 纬度]
// 样式配置
itemStyle: {
areaColor: '#323c48', // 区域颜色
borderColor: '#111', // 边框颜色
borderWidth: 1,
shadowColor: 'rgba(0, 0, 0, 0.5)',
shadowBlur: 10
},
// 高亮样式
emphasis: {
itemStyle: {
areaColor: '#2a333d'
},
label: {
show: true,
color: '#fff'
}
}
},
series: [{
type: 'scatter',
coordinateSystem: 'geo', // 使用地理坐标系
data: [
{ name: '北京', value: [116.4074, 39.9042, 100] },
{ name: '上海', value: [121.4737, 31.2304, 120] }
]
}]
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
多地图叠加
typescript
const option = {
// 两个地理坐标系
geo: [
{
map: 'china',
left: '5%',
right: '55%',
top: '10%',
bottom: '10%'
},
{
map: 'world',
left: '55%',
right: '5%',
top: '10%',
bottom: '10%'
}
],
series: [
{
type: 'scatter',
geoIndex: 0, // 使用第一个geo (中国)
data: chinaData
},
{
type: 'scatter',
geoIndex: 1, // 使用第二个geo (世界)
data: worldData
}
]
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
🗺️ 地图数据加载
注册自定义地图
typescript
import * as echarts from 'echarts';
// 方式1: 从JSON文件加载
async function registerMap() {
const response = await fetch('/maps/china.json');
const geoJson = await response.json();
echarts.registerMap('china-custom', geoJson);
const option = {
geo: {
map: 'china-custom'
}
};
chart.setOption(option);
}
// 方式2: 使用内置地图
// 需要先引入地图数据
import 'echarts/map/js/china.js';
const option = {
geo: {
map: 'china'
}
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
省级地图
typescript
// 注册省级地图
async function loadProvinceMap(province: string) {
const response = await fetch(`/maps/province/${province}.json`);
const geoJson = await response.json();
echarts.registerMap(province, geoJson);
chart.setOption({
geo: {
map: province,
roam: true
},
series: [{
type: 'scatter',
coordinateSystem: 'geo',
data: cityData
}]
});
}
// 使用
loadProvinceMap('guangdong'); // 广东省1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
📍 散点图与飞线
城市分布散点图
typescript
const option = {
geo: {
map: 'china',
roam: true,
itemStyle: {
areaColor: '#323c48',
borderColor: '#111'
},
emphasis: {
itemStyle: {
areaColor: '#2a333d'
}
}
},
tooltip: {
trigger: 'item',
formatter: (params: any) => {
return `${params.name}<br/>数值: ${params.value[2]}`;
}
},
series: [{
type: 'effectScatter', // 带有涟漪特效的散点图
coordinateSystem: 'geo',
data: [
{ name: '北京', value: [116.4074, 39.9042, 150] },
{ name: '上海', value: [121.4737, 31.2304, 180] },
{ name: '广州', value: [113.2644, 23.1291, 120] },
{ name: '深圳', value: [114.0579, 22.5431, 140] },
{ name: '成都', value: [104.0665, 30.5723, 100] }
],
// 涟漪特效
rippleEffect: {
brushType: 'stroke',
scale: 3,
period: 4
},
// 符号大小映射
symbolSize: (val: number[]) => {
return val[2] / 10;
},
// 标签
label: {
show: true,
formatter: '{b}',
position: 'right',
color: '#fff'
},
itemStyle: {
color: '#f4e925'
},
emphasis: {
label: {
show: true
}
}
}]
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
飞线图 (迁徙图)
typescript
const option = {
geo: {
map: 'china',
roam: false,
zoom: 1.2,
itemStyle: {
areaColor: '#323c48',
borderColor: '#404a59'
}
},
series: [
{
name: '迁徙',
type: 'lines',
zlevel: 1,
effect: {
show: true,
period: 6, // 动画周期
trailLength: 0.7, // 尾迹长度
color: '#fff', // 动画标记颜色
symbolSize: 3
},
lineStyle: {
color: '#a6c84c',
width: 0,
curveness: 0.2 // 曲线程度
},
data: generateFlightData()
},
{
name: '迁徙线',
type: 'lines',
zlevel: 2,
effect: {
show: true,
period: 6,
trailLength: 0,
symbol: 'arrow', // 箭头
symbolSize: 6
},
lineStyle: {
color: '#a6c84c',
width: 1,
opacity: 0.6,
curveness: 0.2
},
data: generateFlightData()
}
]
};
function generateFlightData() {
const beijing = [116.4074, 39.9042];
const cities = [
{ name: '上海', coords: [121.4737, 31.2304] },
{ name: '广州', coords: [113.2644, 23.1291] },
{ name: '深圳', coords: [114.0579, 22.5431] },
{ name: '成都', coords: [104.0665, 30.5723] }
];
return cities.map(city => ({
coords: [beijing, city.coords],
name: `北京 -> ${city.name}`
}));
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
🔥 热力图与 Choropleth
人口密度热力图
typescript
const option = {
geo: {
map: 'china',
roam: true,
itemStyle: {
areaColor: '#323c48',
borderColor: '#111'
}
},
visualMap: {
min: 0,
max: 1000,
calculable: true,
inRange: {
color: ['#0c274b', '#1a4a7a', '#2a6fa8', '#4a9fd8', '#7fc8f0', '#b8e6ff']
},
textStyle: {
color: '#fff'
}
},
series: [{
type: 'heatmap',
coordinateSystem: 'geo',
data: generateHeatmapData(),
pointSize: 10,
blurSize: 20
}]
};
function generateHeatmapData(): number[][] {
const data: number[][] = [];
// 主要城市及其人口密度
const cities = [
[116.4074, 39.9042, 800], // 北京
[121.4737, 31.2304, 950], // 上海
[113.2644, 23.1291, 700], // 广州
[114.0579, 22.5431, 850], // 深圳
[104.0665, 30.5723, 600], // 成都
[120.1551, 30.2741, 650], // 杭州
[118.7969, 32.0603, 550] // 南京
];
return cities;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
分级统计图 (Choropleth)
typescript
const option = {
tooltip: {
trigger: 'item',
formatter: (params: any) => {
return `${params.name}<br/>GDP: ${params.value} 亿元`;
}
},
visualMap: {
min: 0,
max: 100000,
left: 'left',
top: 'bottom',
text: ['高', '低'],
calculable: true,
inRange: {
color: ['#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
}
},
geo: {
map: 'china',
roam: true,
label: {
emphasis: {
show: true
}
},
itemStyle: {
normal: {
areaColor: '#323c48',
borderColor: '#111'
},
emphasis: {
areaColor: '#2a333d'
}
}
},
series: [{
name: 'GDP',
type: 'map',
geoIndex: 0,
data: [
{ name: '广东', value: 110000 },
{ name: '江苏', value: 100000 },
{ name: '山东', value: 70000 },
{ name: '浙江', value: 65000 },
{ name: '河南', value: 55000 },
{ name: '四川', value: 48000 },
{ name: '湖北', value: 45000 },
{ name: '福建', value: 43000 },
{ name: '湖南', value: 42000 },
{ name: '上海', value: 38000 }
]
}]
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
💻 实战案例
全国物流监控大屏
typescript
class LogisticsMonitor {
private chart: echarts.ECharts;
constructor(container: HTMLElement) {
this.chart = echarts.init(container);
this.init();
this.startRealtimeUpdate();
}
private init() {
const option = {
title: {
text: '全国物流实时监控',
left: 'center',
textStyle: { color: '#fff' }
},
backgroundColor: '#000',
geo: {
map: 'china',
roam: true,
zoom: 1.2,
label: {
emphasis: { show: false }
},
itemStyle: {
normal: {
areaColor: '#323c48',
borderColor: '#404a59'
},
emphasis: {
areaColor: '#2a333d'
}
}
},
series: [
{
name: '配送中心',
type: 'effectScatter',
coordinateSystem: 'geo',
data: this.getDistributionCenters(),
symbolSize: 15,
rippleEffect: {
brushType: 'stroke',
scale: 4,
period: 3
},
itemStyle: { color: '#f4e925' }
},
{
name: '运输线路',
type: 'lines',
zlevel: 2,
effect: {
show: true,
period: 6,
trailLength: 0.7,
color: '#fff',
symbolSize: 3
},
lineStyle: {
color: '#a6c84c',
width: 0,
curveness: 0.2
},
data: this.getTransportLines()
}
]
};
this.chart.setOption(option);
}
private getDistributionCenters() {
return [
{ name: '北京仓', value: [116.4074, 39.9042] },
{ name: '上海仓', value: [121.4737, 31.2304] },
{ name: '广州仓', value: [113.2644, 23.1291] },
{ name: '成都仓', value: [104.0665, 30.5723] }
];
}
private getTransportLines() {
const beijing = [116.4074, 39.9042];
return [
{ coords: [beijing, [121.4737, 31.2304]] },
{ coords: [beijing, [113.2644, 23.1291]] },
{ coords: [beijing, [104.0665, 30.5723]] }
];
}
private startRealtimeUpdate() {
setInterval(() => {
// 模拟实时更新
this.updateTransportStatus();
}, 5000);
}
private updateTransportStatus() {
// 更新运输状态
console.log('更新运输状态...');
}
resize() {
this.chart.resize();
}
dispose() {
this.chart.dispose();
}
}
// 使用
const monitor = new LogisticsMonitor(document.getElementById('chart')!);
window.addEventListener('resize', () => monitor.resize());1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
🎯 最佳实践总结
✅ DO - 推荐做法
使用effectScatter突出重要位置
typescripttype: 'effectScatter' // 带涟漪效果1飞线图使用双层lines
typescript// 第一层: 尾迹效果 // 第二层: 箭头指示方向1
2合理设置zoom范围
typescriptzoom: 1.2, scaleLimit: { min: 1, max: 10 }1
2
❌ DON'T - 避免做法
- 避免过多飞线导致混乱typescript
// ❌ 不好 - 超过50条飞线 data: Array.from({length: 100}, ...) // ✅ 好 - 控制在20条以内 data: mainRoutes1
2
3
4
5
🔗 相关资源
上一篇: polar极坐标系.md)
下一篇: singleAxis单轴.md)
地理坐标系
{
"title": {
"text": "全国销售分布",
"left": "center"
},
"tooltip": {
"trigger": "item"
},
"visualMap": {
"min": 0,
"max": 1000,
"left": "left",
"top": "bottom",
"text": [
"高",
"低"
],
"calculable": true,
"inRange": {
"color": [
"#e0f3f8",
"#abd9e9",
"#74add1",
"#4575b4",
"#313695"
]
}
},
"geo": {
"map": "china",
"roam": true,
"zoom": 1.2,
"label": {
"emphasis": {
"show": true
}
},
"itemStyle": {
"normal": {
"areaColor": "#323c48",
"borderColor": "#111"
},
"emphasis": {
"areaColor": "#2a333d"
}
}
},
"series": [
{
"type": "map",
"geoIndex": 0,
"data": [
{
"name": "北京",
"value": 850
},
{
"name": "上海",
"value": 920
},
{
"name": "广东",
"value": 780
},
{
"name": "浙江",
"value": 650
},
{
"name": "江苏",
"value": 700
}
]
}
]
}上一篇: polar极坐标系.md)
下一篇: singleAxis单轴.md)
