-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgeo-data-loader.js
More file actions
357 lines (307 loc) · 13.4 KB
/
geo-data-loader.js
File metadata and controls
357 lines (307 loc) · 13.4 KB
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
/**
* 地理数据加载器
* 负责加载和处理真实的中国行政区划GeoJSON数据
*/
class GeoDataLoader {
constructor() {
this.geoData = null;
this.provinces = new Map();
this.loadingPromise = null;
}
/**
* 加载地理数据
* @returns {Promise} 加载完成的Promise
*/
async loadGeoData() {
if (this.loadingPromise) {
return this.loadingPromise;
}
this.loadingPromise = this._fetchGeoData();
return this.loadingPromise;
}
/**
* 获取地理数据(优先使用本地数据)
*/
async _fetchGeoData() {
try {
// 方案1: 优先使用本地GeoJSON数据
const response = await fetch('./geojson-map-china-master/china.json');
if (!response.ok) {
console.warn('本地数据加载失败,尝试在线数据源');
// 降级到在线数据源
return this._fetchOnlineGeoData();
}
this.geoData = await response.json();
this._processGeoData();
console.log('本地地理数据加载成功', this.geoData);
return this.geoData;
} catch (error) {
console.error('加载本地地理数据失败:', error);
// 降级到在线数据源
return this._fetchOnlineGeoData();
}
}
/**
* 加载在线地理数据(降级方案)
*/
async _fetchOnlineGeoData() {
try {
console.log('尝试加载在线地理数据...');
const response = await fetch('https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
this.geoData = await response.json();
this._processGeoData();
console.log('在线地理数据加载成功', this.geoData);
return this.geoData;
} catch (error) {
console.error('在线地理数据加载失败:', error);
// 最终降级到简化数据
return this._loadFallbackData();
}
}
/**
* 处理GeoJSON数据,转换为SVG路径
*/
_processGeoData() {
if (!this.geoData || !this.geoData.features) {
throw new Error('无效的GeoJSON数据格式');
}
this.geoData.features.forEach(feature => {
const properties = feature.properties;
const geometry = feature.geometry;
if (geometry && (geometry.type === 'Polygon' || geometry.type === 'MultiPolygon')) {
const svgPath = this._geometryToSVGPath(geometry);
// 使用id作为省份标识符,兼容本地数据格式
const provinceId = properties.id || properties.adcode;
const provinceName = properties.name;
const provinceCenter = properties.cp || properties.center || this._calculateCentroid(geometry);
this.provinces.set(provinceId, {
id: provinceId,
name: provinceName,
adcode: properties.adcode || provinceId,
center: provinceCenter,
svgPath: svgPath,
bounds: this._calculateBounds(geometry),
geometry: geometry,
size: properties.size || 'unknown',
childNum: properties.childNum || 0
});
}
});
console.log(`成功处理 ${this.provinces.size} 个省份数据`);
}
/**
* 将GeoJSON几何体转换为SVG路径
* @param {Object} geometry GeoJSON几何体
* @returns {string} SVG路径字符串
*/
_geometryToSVGPath(geometry) {
const coordinates = geometry.coordinates;
let pathData = '';
if (geometry.type === 'Polygon') {
pathData = this._polygonToPath(coordinates);
} else if (geometry.type === 'MultiPolygon') {
pathData = coordinates.map(polygon => this._polygonToPath(polygon)).join(' ');
}
return pathData;
}
/**
* 将多边形坐标转换为SVG路径
* @param {Array} coordinates 多边形坐标数组
* @returns {string} SVG路径字符串
*/
_polygonToPath(coordinates) {
return coordinates.map((ring, index) => {
const pathCommands = ring.map((point, pointIndex) => {
const [x, y] = this._projectCoordinate(point);
return pointIndex === 0 ? `M${x},${y}` : `L${x},${y}`;
});
pathCommands.push('Z'); // 闭合路径
return pathCommands.join(' ');
}).join(' ');
}
/**
* 投影坐标转换(经纬度转SVG坐标)
* @param {Array} coordinate [经度, 纬度]
* @returns {Array} [x, y] SVG坐标
*/
_projectCoordinate([lng, lat]) {
// 简化的墨卡托投影,适用于中国地图
const minLng = 73.5; // 中国最西经度
const maxLng = 135.0; // 中国最东经度
const minLat = 18.0; // 中国最南纬度
const maxLat = 53.5; // 中国最北纬度
const mapWidth = 1000;
const mapHeight = 800;
const x = ((lng - minLng) / (maxLng - minLng)) * mapWidth;
const y = mapHeight - ((lat - minLat) / (maxLat - minLat)) * mapHeight;
return [Math.round(x * 100) / 100, Math.round(y * 100) / 100];
}
/**
* 计算几何体的中心点
* @param {Object} geometry GeoJSON几何体
* @returns {Array} [经度, 纬度]
*/
_calculateCentroid(geometry) {
// 简化的质心计算
let totalX = 0, totalY = 0, totalPoints = 0;
const processCoordinates = (coords) => {
coords.forEach(point => {
if (Array.isArray(point[0])) {
processCoordinates(point);
} else {
totalX += point[0];
totalY += point[1];
totalPoints++;
}
});
};
processCoordinates(geometry.coordinates);
return [totalX / totalPoints, totalY / totalPoints];
}
/**
* 计算几何体的边界框
* @param {Object} geometry GeoJSON几何体
* @returns {Object} 边界框 {minX, minY, maxX, maxY}
*/
_calculateBounds(geometry) {
let minX = Infinity, minY = Infinity;
let maxX = -Infinity, maxY = -Infinity;
const processCoordinates = (coords) => {
coords.forEach(point => {
if (Array.isArray(point[0])) {
processCoordinates(point);
} else {
const [x, y] = this._projectCoordinate(point);
minX = Math.min(minX, x);
minY = Math.min(minY, y);
maxX = Math.max(maxX, x);
maxY = Math.max(maxY, y);
}
});
};
processCoordinates(geometry.coordinates);
return { minX, minY, maxX, maxY };
}
/**
* 降级数据加载(使用简化数据)
*/
async _loadFallbackData() {
console.warn('使用降级数据');
// 这里可以加载预先准备的简化数据
return {
type: 'FeatureCollection',
features: [] // 简化的特征数据
};
}
/**
* 获取省份数据
* @param {string} adcode 行政区划代码
* @returns {Object} 省份数据
*/
getProvinceData(adcode) {
return this.provinces.get(adcode);
}
/**
* 获取所有省份数据
* @returns {Map} 所有省份数据
*/
getAllProvinces() {
return this.provinces;
}
/**
* 根据名称查找省份
* @param {string} name 省份名称
* @returns {Object} 省份数据
*/
findProvinceByName(name) {
for (const [adcode, province] of this.provinces) {
if (province.name.includes(name) || name.includes(province.name.replace(/[市省区]/g, ''))) {
return province;
}
}
return null;
}
}
/**
* 省会城市数据映射(匹配本地GeoJSON数据的ID格式)
* 由于GeoJSON通常不包含省会信息,需要手动维护
*/
const PROVINCE_CAPITALS = {
// 直辖市
'11': { name: '北京市', shortName: '京', capital: '北京', fullName: '北京市' },
'12': { name: '天津市', shortName: '津', capital: '天津', fullName: '天津市' },
'31': { name: '上海市', shortName: '沪', capital: '上海', fullName: '上海市' },
'50': { name: '重庆市', shortName: '渝', capital: '重庆', fullName: '重庆市' },
// 省份
'13': { name: '河北省', shortName: '冀', capital: '石家庄', fullName: '河北省' },
'14': { name: '山西省', shortName: '晋', capital: '太原', fullName: '山西省' },
'21': { name: '辽宁省', shortName: '辽', capital: '沈阳', fullName: '辽宁省' },
'22': { name: '吉林省', shortName: '吉', capital: '长春', fullName: '吉林省' },
'23': { name: '黑龙江省', shortName: '黑', capital: '哈尔滨', fullName: '黑龙江省' },
'32': { name: '江苏省', shortName: '苏', capital: '南京', fullName: '江苏省' },
'33': { name: '浙江省', shortName: '浙', capital: '杭州', fullName: '浙江省' },
'34': { name: '安徽省', shortName: '皖', capital: '合肥', fullName: '安徽省' },
'35': { name: '福建省', shortName: '闽', capital: '福州', fullName: '福建省' },
'36': { name: '江西省', shortName: '赣', capital: '南昌', fullName: '江西省' },
'37': { name: '山东省', shortName: '鲁', capital: '济南', fullName: '山东省' },
'41': { name: '河南省', shortName: '豫', capital: '郑州', fullName: '河南省' },
'42': { name: '湖北省', shortName: '鄂', capital: '武汉', fullName: '湖北省' },
'43': { name: '湖南省', shortName: '湘', capital: '长沙', fullName: '湖南省' },
'44': { name: '广东省', shortName: '粤', capital: '广州', fullName: '广东省' },
'46': { name: '海南省', shortName: '琼', capital: '海口', fullName: '海南省' },
'51': { name: '四川省', shortName: '川', capital: '成都', fullName: '四川省' },
'52': { name: '贵州省', shortName: '黔', capital: '贵阳', fullName: '贵州省' },
'53': { name: '云南省', shortName: '滇', capital: '昆明', fullName: '云南省' },
'61': { name: '陕西省', shortName: '陕', capital: '西安', fullName: '陕西省' },
'62': { name: '甘肃省', shortName: '甘', capital: '兰州', fullName: '甘肃省' },
'63': { name: '青海省', shortName: '青', capital: '西宁', fullName: '青海省' },
// 自治区
'15': { name: '内蒙古自治区', shortName: '蒙', capital: '呼和浩特', fullName: '内蒙古自治区' },
'45': { name: '广西壮族自治区', shortName: '桂', capital: '南宁', fullName: '广西壮族自治区' },
'54': { name: '西藏自治区', shortName: '藏', capital: '拉萨', fullName: '西藏自治区' },
'64': { name: '宁夏回族自治区', shortName: '宁', capital: '银川', fullName: '宁夏回族自治区' },
'65': { name: '新疆维吾尔自治区', shortName: '新', capital: '乌鲁木齐', fullName: '新疆维吾尔自治区' },
// 特别行政区
'71': { name: '台湾省', shortName: '台', capital: '台北', fullName: '台湾省' },
'81': { name: '香港特别行政区', shortName: '港', capital: '香港', fullName: '香港特别行政区' },
'82': { name: '澳门特别行政区', shortName: '澳', capital: '澳门', fullName: '澳门特别行政区' }
};
/**
* 获取省份的省会信息(兼容新旧ID格式)
* @param {string} provinceId 省份ID(支持2位或6位格式)
* @returns {Object} 省会信息
*/
function getCapitalInfo(provinceId) {
// 直接匹配
if (PROVINCE_CAPITALS[provinceId]) {
return PROVINCE_CAPITALS[provinceId];
}
// 兼容6位代码格式(去掉后4位0)
if (provinceId.length === 6 && provinceId.endsWith('0000')) {
const shortId = provinceId.substring(0, 2);
return PROVINCE_CAPITALS[shortId];
}
// 兼容其他格式
const fallbackMapping = {
'110000': '11', '120000': '12', '130000': '13', '140000': '14', '150000': '15',
'210000': '21', '220000': '22', '230000': '23', '310000': '31', '320000': '32',
'330000': '33', '340000': '34', '350000': '35', '360000': '36', '370000': '37',
'410000': '41', '420000': '42', '430000': '43', '440000': '44', '450000': '45',
'460000': '46', '500000': '50', '510000': '51', '520000': '52', '530000': '53',
'540000': '54', '610000': '61', '620000': '62', '630000': '63', '640000': '64',
'650000': '65', '710000': '71', '810000': '81', '820000': '82'
};
const mappedId = fallbackMapping[provinceId];
if (mappedId && PROVINCE_CAPITALS[mappedId]) {
return PROVINCE_CAPITALS[mappedId];
}
console.warn(`未找到省份ID ${provinceId} 对应的省会信息`);
return null;
}
// 导出类和工具函数
window.GeoDataLoader = GeoDataLoader;
window.getCapitalInfo = getCapitalInfo;
window.PROVINCE_CAPITALS = PROVINCE_CAPITALS;