my-openlayer 1.0.14 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MyOl.d.ts +128 -128
- package/MyOl.js +381 -382
- package/README.md +292 -48
- package/core/ConfigManager.d.ts +88 -88
- package/core/ConfigManager.js +112 -112
- package/core/DomPoint.d.ts +21 -0
- package/core/DomPoint.js +36 -0
- package/core/EventManager.d.ts +141 -141
- package/core/EventManager.js +316 -316
- package/core/Line.d.ts +109 -109
- package/core/Line.js +288 -283
- package/core/MapBaseLayers.d.ts +234 -234
- package/core/MapBaseLayers.js +573 -573
- package/core/MapTools.d.ts +68 -68
- package/core/MapTools.js +201 -202
- package/core/MeasureHandler.d.ts +65 -65
- package/core/MeasureHandler.js +312 -312
- package/core/Point.d.ts +94 -94
- package/core/Point.js +348 -343
- package/core/Polygon.d.ts +139 -139
- package/core/Polygon.js +529 -529
- package/core/VueTemplatePoint.d.ts +51 -51
- package/core/VueTemplatePoint.js +529 -529
- package/index.d.ts +18 -18
- package/index.js +17 -17
- package/package.json +4 -5
- package/types.d.ts +302 -302
- package/types.js +11 -11
- package/utils/ErrorHandler.d.ts +102 -102
- package/utils/ErrorHandler.js +191 -191
- package/utils/ValidationUtils.d.ts +163 -163
- package/utils/ValidationUtils.js +312 -312
package/MyOl.js
CHANGED
|
@@ -1,382 +1,381 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// OpenLayers 核心导入
|
|
3
|
-
import { register as olProj4Register } from 'ol/proj/proj4';
|
|
4
|
-
import { Projection as olProjProjection, addProjection as olProjAddProjection, fromLonLat as olProjFromLonLat } from 'ol/proj';
|
|
5
|
-
import View from "ol/View";
|
|
6
|
-
import Map from "ol/Map";
|
|
7
|
-
import { defaults as defaultControls } from 'ol/control';
|
|
8
|
-
import proj4 from "proj4";
|
|
9
|
-
// 内部模块导入
|
|
10
|
-
import Polygon from "./core/Polygon";
|
|
11
|
-
import Point from "./core/Point";
|
|
12
|
-
import Line from "./core/Line";
|
|
13
|
-
import MapBaseLayers from "./core/MapBaseLayers";
|
|
14
|
-
import MapTools from "./core/MapTools";
|
|
15
|
-
import { ErrorHandler, MyOpenLayersError, ErrorType } from './utils/ErrorHandler';
|
|
16
|
-
import { EventManager } from './core/EventManager';
|
|
17
|
-
import { ConfigManager } from './core/ConfigManager';
|
|
18
|
-
/**
|
|
19
|
-
* MyOl 地图核心类
|
|
20
|
-
* 提供完整的地图操作功能,包括点、线、面要素管理,底图切换,工具操作等
|
|
21
|
-
*/
|
|
22
|
-
class MyOl {
|
|
23
|
-
/**
|
|
24
|
-
* 构造函数
|
|
25
|
-
* @param id 地图容器 DOM 元素 ID
|
|
26
|
-
* @param options 地图初始化配置
|
|
27
|
-
*/
|
|
28
|
-
constructor(id, options) {
|
|
29
|
-
// 初始化错误处理器(必须最先初始化)
|
|
30
|
-
this.errorHandler = ErrorHandler.getInstance();
|
|
31
|
-
try {
|
|
32
|
-
// 初始化配置管理器
|
|
33
|
-
this.configManager = new ConfigManager();
|
|
34
|
-
// 合并配置(处理 undefined 情况)
|
|
35
|
-
this.options = ConfigManager.mergeOptions(MyOl.DefaultOptions, options || {});
|
|
36
|
-
// 参数验证
|
|
37
|
-
this.validateConstructorParams(id, this.options);
|
|
38
|
-
// 初始化坐标系
|
|
39
|
-
MyOl.initializeProjections();
|
|
40
|
-
// 准备图层
|
|
41
|
-
const layers = Array.isArray(this.options.layers) ? this.options.layers : [];
|
|
42
|
-
// 创建地图实例
|
|
43
|
-
// 确保 view 选项不会传递给 OpenLayers Map 构造函数,避免 "then is not a function" 错误
|
|
44
|
-
// 我们完全控制传递给 Map 的选项,不直接传递用户的 options
|
|
45
|
-
const mapOptions = {
|
|
46
|
-
target: id,
|
|
47
|
-
view: this.options.view || MyOl.createView(this.options),
|
|
48
|
-
layers: layers,
|
|
49
|
-
controls: this.createControls()
|
|
50
|
-
};
|
|
51
|
-
this.map = new Map(mapOptions);
|
|
52
|
-
if (this.options.token && (layers.length === 0 || this.options.annotation)) {
|
|
53
|
-
this.getMapBaseLayers();
|
|
54
|
-
}
|
|
55
|
-
// 初始化基础事件监听(地图错误等)
|
|
56
|
-
this.initializeEventListeners();
|
|
57
|
-
}
|
|
58
|
-
catch (error) {
|
|
59
|
-
this.errorHandler.handleError(new MyOpenLayersError(`地图初始化失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.MAP_ERROR, { id, options }));
|
|
60
|
-
throw error;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* 验证构造函数参数
|
|
65
|
-
* @private
|
|
66
|
-
*/
|
|
67
|
-
validateConstructorParams(id, options) {
|
|
68
|
-
if (!id || typeof id !== 'string') {
|
|
69
|
-
throw new Error('地图容器 ID 必须是非空字符串');
|
|
70
|
-
}
|
|
71
|
-
if (!options || typeof options !== 'object') {
|
|
72
|
-
throw new Error('地图配置选项不能为空');
|
|
73
|
-
}
|
|
74
|
-
// 检查 DOM 元素是否存在
|
|
75
|
-
const element = document.getElementById(id);
|
|
76
|
-
if (!element) {
|
|
77
|
-
throw new Error(`找不到 ID 为 '${id}' 的 DOM 元素`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* 初始化坐标系
|
|
82
|
-
* @private
|
|
83
|
-
*/
|
|
84
|
-
static initializeProjections() {
|
|
85
|
-
// 定义 CGCS2000 坐标系
|
|
86
|
-
proj4.defs(MyOl.PROJECTIONS.CGCS2000, "+proj=longlat +ellps=GRS80 +no_defs");
|
|
87
|
-
proj4.defs(MyOl.PROJECTIONS.CGCS2000_3_DEGREE, "+proj=tmerc +lat_0=0 +lon_0=120 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs");
|
|
88
|
-
// 注册到 OpenLayers
|
|
89
|
-
olProj4Register(proj4);
|
|
90
|
-
// 添加 CGCS2000 投影
|
|
91
|
-
const cgsc2000 = new olProjProjection({
|
|
92
|
-
code: MyOl.PROJECTIONS.CGCS2000,
|
|
93
|
-
extent: [-180, -90, 180, 90],
|
|
94
|
-
worldExtent: [-180, -90, 180, 90],
|
|
95
|
-
units: "degrees"
|
|
96
|
-
});
|
|
97
|
-
olProjAddProjection(cgsc2000);
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* 创建地图控件
|
|
101
|
-
* @private
|
|
102
|
-
*/
|
|
103
|
-
createControls() {
|
|
104
|
-
return defaultControls({
|
|
105
|
-
zoom: false,
|
|
106
|
-
rotate: false,
|
|
107
|
-
attribution: false
|
|
108
|
-
}).extend([]);
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* 初始化事件监听
|
|
112
|
-
* @private
|
|
113
|
-
*/
|
|
114
|
-
initializeEventListeners() {
|
|
115
|
-
const eventManager = this.getEventManager();
|
|
116
|
-
// 地图加载完成事件
|
|
117
|
-
eventManager.on('rendercomplete', (eventData) => {
|
|
118
|
-
console.debug('地图初始化完成', { map: this.map });
|
|
119
|
-
}, { once: true });
|
|
120
|
-
// 地图错误事件
|
|
121
|
-
eventManager.on('error', (eventData) => {
|
|
122
|
-
this.errorHandler.handleError(new MyOpenLayersError('地图渲染错误', ErrorType.MAP_ERROR, { error: eventData.error }));
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* 创建地图视图
|
|
127
|
-
* @param options 视图配置
|
|
128
|
-
* @returns View 地图视图实例
|
|
129
|
-
*/
|
|
130
|
-
static createView(options = MyOl.DefaultOptions) {
|
|
131
|
-
try {
|
|
132
|
-
const projection = new olProjProjection({
|
|
133
|
-
code: MyOl.PROJECTIONS.CGCS2000,
|
|
134
|
-
extent: [-180, -90, 180, 90],
|
|
135
|
-
worldExtent: [-180, -90, 180, 90],
|
|
136
|
-
units: "degrees"
|
|
137
|
-
});
|
|
138
|
-
const viewOptions = {
|
|
139
|
-
projection,
|
|
140
|
-
center: olProjFromLonLat(options.center, projection),
|
|
141
|
-
zoom: options.zoom ?? MyOl.DefaultOptions.zoom,
|
|
142
|
-
minZoom: options.minZoom,
|
|
143
|
-
maxZoom: options.maxZoom,
|
|
144
|
-
...(options.extent && { extent: options.extent })
|
|
145
|
-
};
|
|
146
|
-
return new View(viewOptions);
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
throw new MyOpenLayersError(`视图创建失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.MAP_ERROR, { options });
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* 获取视图(向后兼容)
|
|
154
|
-
* @deprecated 请使用 createView 方法
|
|
155
|
-
*/
|
|
156
|
-
static getView(options = MyOl.DefaultOptions) {
|
|
157
|
-
console.warn('getView 方法已废弃,请使用 createView 方法');
|
|
158
|
-
return MyOl.createView(options);
|
|
159
|
-
}
|
|
160
|
-
// ==========================================
|
|
161
|
-
// 功能模块获取方法(懒加载模式)
|
|
162
|
-
// ==========================================
|
|
163
|
-
/**
|
|
164
|
-
* 获取面要素操作模块
|
|
165
|
-
* @returns Polygon 面要素操作实例
|
|
166
|
-
*/
|
|
167
|
-
getPolygon() {
|
|
168
|
-
try {
|
|
169
|
-
if (!this._polygon) {
|
|
170
|
-
this._polygon = new Polygon(this.map);
|
|
171
|
-
console.debug('面要素模块已加载');
|
|
172
|
-
}
|
|
173
|
-
return this._polygon;
|
|
174
|
-
}
|
|
175
|
-
catch (error) {
|
|
176
|
-
this.errorHandler.handleError(new MyOpenLayersError('面要素模块初始化失败', ErrorType.COMPONENT_ERROR, { error }));
|
|
177
|
-
throw error;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* 获取底图图层管理模块
|
|
182
|
-
* @returns MapBaseLayers 底图管理实例
|
|
183
|
-
*/
|
|
184
|
-
getMapBaseLayers() {
|
|
185
|
-
try {
|
|
186
|
-
if (!this._baseLayers) {
|
|
187
|
-
// 检查是否设置了自定义底图
|
|
188
|
-
if (Array.isArray(this.options.layers)) {
|
|
189
|
-
console.warn('已设置默认底图,MapBaseLayers 中的 switchBaseLayer 方法将失效');
|
|
190
|
-
}
|
|
191
|
-
const layerOptions = {
|
|
192
|
-
layers: this.options.layers,
|
|
193
|
-
annotation: this.options.annotation,
|
|
194
|
-
zIndex: 1,
|
|
195
|
-
mapClip: !!this.options.mapClipData,
|
|
196
|
-
mapClipData: this.options.mapClipData,
|
|
197
|
-
token: this.options.token || ''
|
|
198
|
-
};
|
|
199
|
-
this._baseLayers = new MapBaseLayers(this.map, layerOptions);
|
|
200
|
-
console.debug('基础图层模块已加载');
|
|
201
|
-
}
|
|
202
|
-
return this._baseLayers;
|
|
203
|
-
}
|
|
204
|
-
catch (error) {
|
|
205
|
-
this.errorHandler.handleError(new MyOpenLayersError('基础图层模块初始化失败', ErrorType.COMPONENT_ERROR, { error }));
|
|
206
|
-
throw error;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* 获取点要素操作模块
|
|
211
|
-
* @returns Point 点要素操作实例
|
|
212
|
-
*/
|
|
213
|
-
getPoint() {
|
|
214
|
-
try {
|
|
215
|
-
if (!this._point) {
|
|
216
|
-
this._point = new Point(this.map);
|
|
217
|
-
console.debug('点要素模块已加载');
|
|
218
|
-
}
|
|
219
|
-
return this._point;
|
|
220
|
-
}
|
|
221
|
-
catch (error) {
|
|
222
|
-
this.errorHandler.handleError(new MyOpenLayersError('点要素模块初始化失败', ErrorType.COMPONENT_ERROR, { error }));
|
|
223
|
-
throw error;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* 获取线要素操作模块
|
|
228
|
-
* @returns Line 线要素操作实例
|
|
229
|
-
*/
|
|
230
|
-
getLine() {
|
|
231
|
-
try {
|
|
232
|
-
if (!this._line) {
|
|
233
|
-
this._line = new Line(this.map);
|
|
234
|
-
console.debug('线要素模块已加载');
|
|
235
|
-
}
|
|
236
|
-
return this._line;
|
|
237
|
-
}
|
|
238
|
-
catch (error) {
|
|
239
|
-
this.errorHandler.handleError(new MyOpenLayersError('线要素模块初始化失败', ErrorType.COMPONENT_ERROR, { error }));
|
|
240
|
-
throw error;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* 获取地图工具模块
|
|
245
|
-
* @returns MapTools 地图工具实例
|
|
246
|
-
*/
|
|
247
|
-
getTools() {
|
|
248
|
-
try {
|
|
249
|
-
if (!this._mapTools) {
|
|
250
|
-
this._mapTools = new MapTools(this.map);
|
|
251
|
-
console.debug('工具模块已加载');
|
|
252
|
-
}
|
|
253
|
-
return this._mapTools;
|
|
254
|
-
}
|
|
255
|
-
catch (error) {
|
|
256
|
-
this.errorHandler.handleError(new MyOpenLayersError('工具模块初始化失败', ErrorType.COMPONENT_ERROR, { error }));
|
|
257
|
-
throw error;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
// ==========================================
|
|
261
|
-
// 地图操作方法
|
|
262
|
-
// ==========================================
|
|
263
|
-
/**
|
|
264
|
-
* 重置地图位置到初始中心点
|
|
265
|
-
* @param duration 动画持续时间(毫秒)
|
|
266
|
-
*/
|
|
267
|
-
resetPosition(duration = 3000) {
|
|
268
|
-
try {
|
|
269
|
-
if (!this.options.center) {
|
|
270
|
-
throw new Error('未设置中心点,无法重置位置');
|
|
271
|
-
}
|
|
272
|
-
const [longitude, latitude] = this.options.center;
|
|
273
|
-
this.locationAction(longitude, latitude, this.options.zoom, duration);
|
|
274
|
-
}
|
|
275
|
-
catch (error) {
|
|
276
|
-
this.errorHandler.handleError(new MyOpenLayersError(`重置地图位置失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.MAP_ERROR, { center: this.options.center, duration }));
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* 地图定位到指定坐标
|
|
281
|
-
* @param longitude 经度
|
|
282
|
-
* @param latitude 纬度
|
|
283
|
-
* @param zoom 缩放级别
|
|
284
|
-
* @param duration 动画持续时间(毫秒)
|
|
285
|
-
*/
|
|
286
|
-
locationAction(longitude, latitude, zoom = 20, duration = 3000) {
|
|
287
|
-
try {
|
|
288
|
-
// 参数验证
|
|
289
|
-
if (typeof longitude !== 'number' || typeof latitude !== 'number') {
|
|
290
|
-
throw new Error('经纬度必须是数字类型');
|
|
291
|
-
}
|
|
292
|
-
if (longitude < -180 || longitude > 180) {
|
|
293
|
-
throw new Error('经度值必须在 -180 到 180 之间');
|
|
294
|
-
}
|
|
295
|
-
if (latitude < -90 || latitude > 90) {
|
|
296
|
-
throw new Error('纬度值必须在 -90 到 90 之间');
|
|
297
|
-
}
|
|
298
|
-
this.getPoint().locationAction(longitude, latitude, zoom, duration);
|
|
299
|
-
// 记录定位操作
|
|
300
|
-
console.debug('地图定位完成', {
|
|
301
|
-
longitude,
|
|
302
|
-
latitude,
|
|
303
|
-
zoom,
|
|
304
|
-
duration
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
catch (error) {
|
|
308
|
-
this.errorHandler.handleError(new MyOpenLayersError(`地图定位失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.MAP_ERROR, { longitude, latitude, zoom, duration }));
|
|
309
|
-
throw error;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
// ==========================================
|
|
313
|
-
// 管理器访问方法
|
|
314
|
-
// ==========================================
|
|
315
|
-
/**
|
|
316
|
-
* 获取错误处理器实例
|
|
317
|
-
* @returns ErrorHandler 错误处理器
|
|
318
|
-
*/
|
|
319
|
-
getErrorHandler() {
|
|
320
|
-
return this.errorHandler;
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* 获取事件管理器实例
|
|
324
|
-
* @returns EventManager 事件管理器
|
|
325
|
-
*/
|
|
326
|
-
getEventManager() {
|
|
327
|
-
if (!this._eventManager) {
|
|
328
|
-
this._eventManager = new EventManager(this.map);
|
|
329
|
-
}
|
|
330
|
-
return this._eventManager;
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* 获取配置管理器实例
|
|
334
|
-
* @returns ConfigManager 配置管理器
|
|
335
|
-
*/
|
|
336
|
-
getConfigManager() {
|
|
337
|
-
return this.configManager;
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* 获取当前地图配置
|
|
341
|
-
* @returns MapInitType 地图配置
|
|
342
|
-
*/
|
|
343
|
-
getMapOptions() {
|
|
344
|
-
return Object.freeze({ ...this.options });
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* 销毁地图实例和相关资源
|
|
348
|
-
*/
|
|
349
|
-
destroy() {
|
|
350
|
-
try {
|
|
351
|
-
// 清理事件监听(仅在已初始化时)
|
|
352
|
-
if (this._eventManager) {
|
|
353
|
-
this._eventManager.clear();
|
|
354
|
-
}
|
|
355
|
-
// 销毁功能模块
|
|
356
|
-
this._point = undefined;
|
|
357
|
-
this._line = undefined;
|
|
358
|
-
this._polygon = undefined;
|
|
359
|
-
this._mapTools = undefined;
|
|
360
|
-
this._baseLayers = undefined;
|
|
361
|
-
// 销毁地图
|
|
362
|
-
this.map.setTarget(undefined);
|
|
363
|
-
console.debug('地图实例已销毁', { map: this.map });
|
|
364
|
-
}
|
|
365
|
-
catch (error) {
|
|
366
|
-
this.errorHandler.handleError(new MyOpenLayersError(`销毁地图失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.MAP_ERROR));
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
// 默认配置
|
|
371
|
-
MyOl.DefaultOptions = {
|
|
372
|
-
layers: undefined,
|
|
373
|
-
zoom: 10,
|
|
374
|
-
center: [119.81, 29.969],
|
|
375
|
-
extent: undefined
|
|
376
|
-
};
|
|
377
|
-
// 坐标系配置
|
|
378
|
-
MyOl.PROJECTIONS = {
|
|
379
|
-
CGCS2000: "EPSG:4490",
|
|
380
|
-
CGCS2000_3_DEGREE: "EPSG:4549"
|
|
381
|
-
};
|
|
382
|
-
export default MyOl;
|
|
1
|
+
"use strict";
|
|
2
|
+
// OpenLayers 核心导入
|
|
3
|
+
import { register as olProj4Register } from 'ol/proj/proj4';
|
|
4
|
+
import { Projection as olProjProjection, addProjection as olProjAddProjection, fromLonLat as olProjFromLonLat } from 'ol/proj';
|
|
5
|
+
import View from "ol/View";
|
|
6
|
+
import Map from "ol/Map";
|
|
7
|
+
import { defaults as defaultControls } from 'ol/control';
|
|
8
|
+
import proj4 from "proj4";
|
|
9
|
+
// 内部模块导入
|
|
10
|
+
import Polygon from "./core/Polygon";
|
|
11
|
+
import Point from "./core/Point";
|
|
12
|
+
import Line from "./core/Line";
|
|
13
|
+
import MapBaseLayers from "./core/MapBaseLayers";
|
|
14
|
+
import MapTools from "./core/MapTools";
|
|
15
|
+
import { ErrorHandler, MyOpenLayersError, ErrorType } from './utils/ErrorHandler';
|
|
16
|
+
import { EventManager } from './core/EventManager';
|
|
17
|
+
import { ConfigManager } from './core/ConfigManager';
|
|
18
|
+
/**
|
|
19
|
+
* MyOl 地图核心类
|
|
20
|
+
* 提供完整的地图操作功能,包括点、线、面要素管理,底图切换,工具操作等
|
|
21
|
+
*/
|
|
22
|
+
export default class MyOl {
|
|
23
|
+
/**
|
|
24
|
+
* 构造函数
|
|
25
|
+
* @param id 地图容器 DOM 元素 ID
|
|
26
|
+
* @param options 地图初始化配置
|
|
27
|
+
*/
|
|
28
|
+
constructor(id, options) {
|
|
29
|
+
// 初始化错误处理器(必须最先初始化)
|
|
30
|
+
this.errorHandler = ErrorHandler.getInstance();
|
|
31
|
+
try {
|
|
32
|
+
// 初始化配置管理器
|
|
33
|
+
this.configManager = new ConfigManager();
|
|
34
|
+
// 合并配置(处理 undefined 情况)
|
|
35
|
+
this.options = ConfigManager.mergeOptions(MyOl.DefaultOptions, options || {});
|
|
36
|
+
// 参数验证
|
|
37
|
+
this.validateConstructorParams(id, this.options);
|
|
38
|
+
// 初始化坐标系
|
|
39
|
+
MyOl.initializeProjections();
|
|
40
|
+
// 准备图层
|
|
41
|
+
const layers = Array.isArray(this.options.layers) ? this.options.layers : [];
|
|
42
|
+
// 创建地图实例
|
|
43
|
+
// 确保 view 选项不会传递给 OpenLayers Map 构造函数,避免 "then is not a function" 错误
|
|
44
|
+
// 我们完全控制传递给 Map 的选项,不直接传递用户的 options
|
|
45
|
+
const mapOptions = {
|
|
46
|
+
target: id,
|
|
47
|
+
view: this.options.view || MyOl.createView(this.options),
|
|
48
|
+
layers: layers,
|
|
49
|
+
controls: this.createControls()
|
|
50
|
+
};
|
|
51
|
+
this.map = new Map(mapOptions);
|
|
52
|
+
if (this.options.token && (layers.length === 0 || this.options.annotation)) {
|
|
53
|
+
this.getMapBaseLayers();
|
|
54
|
+
}
|
|
55
|
+
// 初始化基础事件监听(地图错误等)
|
|
56
|
+
this.initializeEventListeners();
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
this.errorHandler.handleError(new MyOpenLayersError(`地图初始化失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.MAP_ERROR, { id, options }));
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 验证构造函数参数
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
validateConstructorParams(id, options) {
|
|
68
|
+
if (!id || typeof id !== 'string') {
|
|
69
|
+
throw new Error('地图容器 ID 必须是非空字符串');
|
|
70
|
+
}
|
|
71
|
+
if (!options || typeof options !== 'object') {
|
|
72
|
+
throw new Error('地图配置选项不能为空');
|
|
73
|
+
}
|
|
74
|
+
// 检查 DOM 元素是否存在
|
|
75
|
+
const element = document.getElementById(id);
|
|
76
|
+
if (!element) {
|
|
77
|
+
throw new Error(`找不到 ID 为 '${id}' 的 DOM 元素`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 初始化坐标系
|
|
82
|
+
* @private
|
|
83
|
+
*/
|
|
84
|
+
static initializeProjections() {
|
|
85
|
+
// 定义 CGCS2000 坐标系
|
|
86
|
+
proj4.defs(MyOl.PROJECTIONS.CGCS2000, "+proj=longlat +ellps=GRS80 +no_defs");
|
|
87
|
+
proj4.defs(MyOl.PROJECTIONS.CGCS2000_3_DEGREE, "+proj=tmerc +lat_0=0 +lon_0=120 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs");
|
|
88
|
+
// 注册到 OpenLayers
|
|
89
|
+
olProj4Register(proj4);
|
|
90
|
+
// 添加 CGCS2000 投影
|
|
91
|
+
const cgsc2000 = new olProjProjection({
|
|
92
|
+
code: MyOl.PROJECTIONS.CGCS2000,
|
|
93
|
+
extent: [-180, -90, 180, 90],
|
|
94
|
+
worldExtent: [-180, -90, 180, 90],
|
|
95
|
+
units: "degrees"
|
|
96
|
+
});
|
|
97
|
+
olProjAddProjection(cgsc2000);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* 创建地图控件
|
|
101
|
+
* @private
|
|
102
|
+
*/
|
|
103
|
+
createControls() {
|
|
104
|
+
return defaultControls({
|
|
105
|
+
zoom: false,
|
|
106
|
+
rotate: false,
|
|
107
|
+
attribution: false
|
|
108
|
+
}).extend([]);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* 初始化事件监听
|
|
112
|
+
* @private
|
|
113
|
+
*/
|
|
114
|
+
initializeEventListeners() {
|
|
115
|
+
const eventManager = this.getEventManager();
|
|
116
|
+
// 地图加载完成事件
|
|
117
|
+
eventManager.on('rendercomplete', (eventData) => {
|
|
118
|
+
console.debug('地图初始化完成', { map: this.map });
|
|
119
|
+
}, { once: true });
|
|
120
|
+
// 地图错误事件
|
|
121
|
+
eventManager.on('error', (eventData) => {
|
|
122
|
+
this.errorHandler.handleError(new MyOpenLayersError('地图渲染错误', ErrorType.MAP_ERROR, { error: eventData.error }));
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 创建地图视图
|
|
127
|
+
* @param options 视图配置
|
|
128
|
+
* @returns View 地图视图实例
|
|
129
|
+
*/
|
|
130
|
+
static createView(options = MyOl.DefaultOptions) {
|
|
131
|
+
try {
|
|
132
|
+
const projection = new olProjProjection({
|
|
133
|
+
code: MyOl.PROJECTIONS.CGCS2000,
|
|
134
|
+
extent: [-180, -90, 180, 90],
|
|
135
|
+
worldExtent: [-180, -90, 180, 90],
|
|
136
|
+
units: "degrees"
|
|
137
|
+
});
|
|
138
|
+
const viewOptions = {
|
|
139
|
+
projection,
|
|
140
|
+
center: olProjFromLonLat(options.center, projection),
|
|
141
|
+
zoom: options.zoom ?? MyOl.DefaultOptions.zoom,
|
|
142
|
+
minZoom: options.minZoom,
|
|
143
|
+
maxZoom: options.maxZoom,
|
|
144
|
+
...(options.extent && { extent: options.extent })
|
|
145
|
+
};
|
|
146
|
+
return new View(viewOptions);
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
throw new MyOpenLayersError(`视图创建失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.MAP_ERROR, { options });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* 获取视图(向后兼容)
|
|
154
|
+
* @deprecated 请使用 createView 方法
|
|
155
|
+
*/
|
|
156
|
+
static getView(options = MyOl.DefaultOptions) {
|
|
157
|
+
console.warn('getView 方法已废弃,请使用 createView 方法');
|
|
158
|
+
return MyOl.createView(options);
|
|
159
|
+
}
|
|
160
|
+
// ==========================================
|
|
161
|
+
// 功能模块获取方法(懒加载模式)
|
|
162
|
+
// ==========================================
|
|
163
|
+
/**
|
|
164
|
+
* 获取面要素操作模块
|
|
165
|
+
* @returns Polygon 面要素操作实例
|
|
166
|
+
*/
|
|
167
|
+
getPolygon() {
|
|
168
|
+
try {
|
|
169
|
+
if (!this._polygon) {
|
|
170
|
+
this._polygon = new Polygon(this.map);
|
|
171
|
+
console.debug('面要素模块已加载');
|
|
172
|
+
}
|
|
173
|
+
return this._polygon;
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
this.errorHandler.handleError(new MyOpenLayersError('面要素模块初始化失败', ErrorType.COMPONENT_ERROR, { error }));
|
|
177
|
+
throw error;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* 获取底图图层管理模块
|
|
182
|
+
* @returns MapBaseLayers 底图管理实例
|
|
183
|
+
*/
|
|
184
|
+
getMapBaseLayers() {
|
|
185
|
+
try {
|
|
186
|
+
if (!this._baseLayers) {
|
|
187
|
+
// 检查是否设置了自定义底图
|
|
188
|
+
if (Array.isArray(this.options.layers)) {
|
|
189
|
+
console.warn('已设置默认底图,MapBaseLayers 中的 switchBaseLayer 方法将失效');
|
|
190
|
+
}
|
|
191
|
+
const layerOptions = {
|
|
192
|
+
layers: this.options.layers,
|
|
193
|
+
annotation: this.options.annotation,
|
|
194
|
+
zIndex: 1,
|
|
195
|
+
mapClip: !!this.options.mapClipData,
|
|
196
|
+
mapClipData: this.options.mapClipData,
|
|
197
|
+
token: this.options.token || ''
|
|
198
|
+
};
|
|
199
|
+
this._baseLayers = new MapBaseLayers(this.map, layerOptions);
|
|
200
|
+
console.debug('基础图层模块已加载');
|
|
201
|
+
}
|
|
202
|
+
return this._baseLayers;
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
this.errorHandler.handleError(new MyOpenLayersError('基础图层模块初始化失败', ErrorType.COMPONENT_ERROR, { error }));
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* 获取点要素操作模块
|
|
211
|
+
* @returns Point 点要素操作实例
|
|
212
|
+
*/
|
|
213
|
+
getPoint() {
|
|
214
|
+
try {
|
|
215
|
+
if (!this._point) {
|
|
216
|
+
this._point = new Point(this.map);
|
|
217
|
+
console.debug('点要素模块已加载');
|
|
218
|
+
}
|
|
219
|
+
return this._point;
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
this.errorHandler.handleError(new MyOpenLayersError('点要素模块初始化失败', ErrorType.COMPONENT_ERROR, { error }));
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* 获取线要素操作模块
|
|
228
|
+
* @returns Line 线要素操作实例
|
|
229
|
+
*/
|
|
230
|
+
getLine() {
|
|
231
|
+
try {
|
|
232
|
+
if (!this._line) {
|
|
233
|
+
this._line = new Line(this.map);
|
|
234
|
+
console.debug('线要素模块已加载');
|
|
235
|
+
}
|
|
236
|
+
return this._line;
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
this.errorHandler.handleError(new MyOpenLayersError('线要素模块初始化失败', ErrorType.COMPONENT_ERROR, { error }));
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* 获取地图工具模块
|
|
245
|
+
* @returns MapTools 地图工具实例
|
|
246
|
+
*/
|
|
247
|
+
getTools() {
|
|
248
|
+
try {
|
|
249
|
+
if (!this._mapTools) {
|
|
250
|
+
this._mapTools = new MapTools(this.map);
|
|
251
|
+
console.debug('工具模块已加载');
|
|
252
|
+
}
|
|
253
|
+
return this._mapTools;
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
this.errorHandler.handleError(new MyOpenLayersError('工具模块初始化失败', ErrorType.COMPONENT_ERROR, { error }));
|
|
257
|
+
throw error;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// ==========================================
|
|
261
|
+
// 地图操作方法
|
|
262
|
+
// ==========================================
|
|
263
|
+
/**
|
|
264
|
+
* 重置地图位置到初始中心点
|
|
265
|
+
* @param duration 动画持续时间(毫秒)
|
|
266
|
+
*/
|
|
267
|
+
resetPosition(duration = 3000) {
|
|
268
|
+
try {
|
|
269
|
+
if (!this.options.center) {
|
|
270
|
+
throw new Error('未设置中心点,无法重置位置');
|
|
271
|
+
}
|
|
272
|
+
const [longitude, latitude] = this.options.center;
|
|
273
|
+
this.locationAction(longitude, latitude, this.options.zoom, duration);
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
this.errorHandler.handleError(new MyOpenLayersError(`重置地图位置失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.MAP_ERROR, { center: this.options.center, duration }));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* 地图定位到指定坐标
|
|
281
|
+
* @param longitude 经度
|
|
282
|
+
* @param latitude 纬度
|
|
283
|
+
* @param zoom 缩放级别
|
|
284
|
+
* @param duration 动画持续时间(毫秒)
|
|
285
|
+
*/
|
|
286
|
+
locationAction(longitude, latitude, zoom = 20, duration = 3000) {
|
|
287
|
+
try {
|
|
288
|
+
// 参数验证
|
|
289
|
+
if (typeof longitude !== 'number' || typeof latitude !== 'number') {
|
|
290
|
+
throw new Error('经纬度必须是数字类型');
|
|
291
|
+
}
|
|
292
|
+
if (longitude < -180 || longitude > 180) {
|
|
293
|
+
throw new Error('经度值必须在 -180 到 180 之间');
|
|
294
|
+
}
|
|
295
|
+
if (latitude < -90 || latitude > 90) {
|
|
296
|
+
throw new Error('纬度值必须在 -90 到 90 之间');
|
|
297
|
+
}
|
|
298
|
+
this.getPoint().locationAction(longitude, latitude, zoom, duration);
|
|
299
|
+
// 记录定位操作
|
|
300
|
+
console.debug('地图定位完成', {
|
|
301
|
+
longitude,
|
|
302
|
+
latitude,
|
|
303
|
+
zoom,
|
|
304
|
+
duration
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
this.errorHandler.handleError(new MyOpenLayersError(`地图定位失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.MAP_ERROR, { longitude, latitude, zoom, duration }));
|
|
309
|
+
throw error;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// ==========================================
|
|
313
|
+
// 管理器访问方法
|
|
314
|
+
// ==========================================
|
|
315
|
+
/**
|
|
316
|
+
* 获取错误处理器实例
|
|
317
|
+
* @returns ErrorHandler 错误处理器
|
|
318
|
+
*/
|
|
319
|
+
getErrorHandler() {
|
|
320
|
+
return this.errorHandler;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* 获取事件管理器实例
|
|
324
|
+
* @returns EventManager 事件管理器
|
|
325
|
+
*/
|
|
326
|
+
getEventManager() {
|
|
327
|
+
if (!this._eventManager) {
|
|
328
|
+
this._eventManager = new EventManager(this.map);
|
|
329
|
+
}
|
|
330
|
+
return this._eventManager;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* 获取配置管理器实例
|
|
334
|
+
* @returns ConfigManager 配置管理器
|
|
335
|
+
*/
|
|
336
|
+
getConfigManager() {
|
|
337
|
+
return this.configManager;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* 获取当前地图配置
|
|
341
|
+
* @returns MapInitType 地图配置
|
|
342
|
+
*/
|
|
343
|
+
getMapOptions() {
|
|
344
|
+
return Object.freeze({ ...this.options });
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* 销毁地图实例和相关资源
|
|
348
|
+
*/
|
|
349
|
+
destroy() {
|
|
350
|
+
try {
|
|
351
|
+
// 清理事件监听(仅在已初始化时)
|
|
352
|
+
if (this._eventManager) {
|
|
353
|
+
this._eventManager.clear();
|
|
354
|
+
}
|
|
355
|
+
// 销毁功能模块
|
|
356
|
+
this._point = undefined;
|
|
357
|
+
this._line = undefined;
|
|
358
|
+
this._polygon = undefined;
|
|
359
|
+
this._mapTools = undefined;
|
|
360
|
+
this._baseLayers = undefined;
|
|
361
|
+
// 销毁地图
|
|
362
|
+
this.map.setTarget(undefined);
|
|
363
|
+
console.debug('地图实例已销毁', { map: this.map });
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
this.errorHandler.handleError(new MyOpenLayersError(`销毁地图失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.MAP_ERROR));
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// 默认配置
|
|
371
|
+
MyOl.DefaultOptions = {
|
|
372
|
+
layers: undefined,
|
|
373
|
+
zoom: 10,
|
|
374
|
+
center: [119.81, 29.969],
|
|
375
|
+
extent: undefined
|
|
376
|
+
};
|
|
377
|
+
// 坐标系配置
|
|
378
|
+
MyOl.PROJECTIONS = {
|
|
379
|
+
CGCS2000: "EPSG:4490",
|
|
380
|
+
CGCS2000_3_DEGREE: "EPSG:4549"
|
|
381
|
+
};
|