my-openlayer 2.4.2 → 2.4.4

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/README.md CHANGED
@@ -1,1502 +1,156 @@
1
- # my-openlayer
2
-
3
- my-openlayer 是一个基于 [OpenLayers](https://openlayers.org/) 的现代地图组件库,专为 Web GIS 应用开发者设计。提供完整的 TypeScript 支持、模块化的类型定义、强大的错误处理和事件管理系统,支持天地图底图加载、要素绘制、图层管理、事件监听等丰富功能,极大提升地图开发效率。支持 TypeScript,具备完整的类型定义和模块化设计。
4
-
5
- [![npm version](https://img.shields.io/npm/v/my-openlayer.svg)](https://www.npmjs.com/package/my-openlayer)
6
- [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
7
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
-
9
- ---
10
-
11
- ## 项目概述
12
-
13
- - 项目名称:`my-openlayer`
14
- - 用途:基于 OpenLayers 的 TypeScript 地图组件库,提供点/线/面要素、底图切换、热力图、事件与配置管理等能力,面向 Web GIS 开发者
15
- - 目标用户:Web GIS 开发者、可视化工程师、前端开发者
16
- - 状态徽章:
17
- - [![npm](https://img.shields.io/npm/v/my-openlayer.svg)](https://www.npmjs.com/package/my-openlayer)
18
- - ![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)
19
- - ![License](https://img.shields.io/badge/License-MIT-yellow.svg)
20
- - ![Build](https://img.shields.io/badge/build-local%20(vite)-blue.svg)
21
- - ![Coverage](https://img.shields.io/badge/coverage-not%20configured-lightgrey.svg)
22
- - ![Node](https://img.shields.io/badge/node-%3E%3D18.0.0-6DA55F.svg)
23
- - ![ol](https://img.shields.io/badge/ol-^10.6.1-blue.svg)
24
-
25
- ## 环境要求
26
-
27
- - Node.js >= 18(Vite 5 要求)
28
- - 包管理器:npm / yarn / pnpm
29
- - 运行时依赖:`ol@^10.6.1`、`proj4@^2.7.5`、`@turf/turf@^7.2.0`
30
- - 开发依赖:`vite@^5.4.10`、`@vitejs/plugin-vue@^5.0.4`、`typescript@~5.6.2`、`vue-tsc@^2.0.6`
31
-
32
- ## 安装指南
33
-
34
- - 安装库:`npm i my-openlayer` 或 `yarn add my-openlayer` 或 `pnpm add my-openlayer`
35
- - 示例与开发:
36
- - 安装依赖:`npm i`
37
- - 开发示例:`npm run dev`
38
- - 构建库:`npm run build`
39
- - 配置文件:
40
- - TypeScript:`tsconfig.json`(声明输出 `dist/`)
41
- - Vite:`vite.config.ts`(插件:@vitejs/plugin-vue、vite-plugin-libcss)
42
- - 环境变量:`.env` 设置 `VITE_TIANDITU_TOKEN=your_token`
43
-
44
- ## 使用说明
45
-
46
- - 主要功能的使用参考下文「详细用法」与「API 文档与示例」
47
- - 示例代码与截图:运行 `npm run dev` 后查看 `examples/App.vue` 渲染效果(截图略)
48
- - FAQ:见下文「常见问题」
49
-
50
- ## 开发指南
51
-
52
- - 项目结构:
53
- - `src/` 核心库源码;`src/core` 包含 BaseLayers/Tools/Point/Line/Polygon/Select 等模块
54
- - `examples/` Vue3 + Vite 示例;入口 `index.html` → `examples/main.ts`
55
- - `dist/` 构建输出;`temp-publish/` 发布前整理产物
56
- - 配置与脚本:`package.json`、`tsconfig.json`、`vite.config.ts`、`scripts/prepare-publish.cjs`
57
- - 开发环境搭建:Node 18+,`npm i` 安装依赖,`npm run dev` 启动示例,`.env` 设置 `VITE_TIANDITU_TOKEN`
58
- - 代码贡献规范:分支 `feature/xxx`、`fix/xxx`;`type(scope): subject` 提交信息;TypeScript 严格类型,2 空格缩进
59
-
60
- ## 许可证信息
61
-
62
- - 许可证:MIT(见 `LICENSE`)
63
- - 版权声明:Copyright (c) 2025 cuteyuchen
64
-
65
- ## 目录
66
-
67
- - [功能亮点](#功能亮点)
68
- - [安装](#安装)
69
- - [快速上手](#快速上手)
70
- - [详细用法](#详细用法)
71
- - [高级功能](#高级功能)
72
- - [API 文档与示例](#api-文档与示例)
73
- - [类型定义](#类型定义)
74
- - [迁移指南](#迁移指南)
75
- - [依赖](#依赖)
76
- - [贡献指南](#贡献指南)
77
- - [常见问题](#常见问题)
78
- - [许可证](#许可证)
79
- - [联系方式](#联系方式)
80
-
81
- ---
82
-
83
- ## 功能亮点
84
-
85
- - **🗺️ 底图管理 (MapBaseLayers)**
86
- - 支持天地图矢量、影像、地形底图切换
87
- - 动态切换底图与注记图层管理
88
- - 地图裁剪与自定义范围显示
89
- - 支持自定义底图源和配置
90
-
91
- - **📍 要素操作**
92
- - **点位管理 (Point)**:点位标注(支持自定义图标、文字、聚合、闪烁)
93
- - **线要素绘制 (Line)**:线要素绘制(支持样式自定义、河流分级显示)
94
- - **面要素 (Polygon)**:面要素绘制与分区高亮
95
- - **Vue组件支持 (VueTemplatePoint)**:DOM 点位(支持 Vue 组件渲染,完整生命周期管理)
96
- - 热力图、图片图层
97
- - 动态要素颜色更新
98
-
99
- - **🛠️ 地图工具**
100
- - **测量工具 (MeasureHandler)**:距离和面积测量
101
- - **地图工具 (MapTools)**:图层管理(获取、移除、显隐控制)
102
- - **事件管理 (EventManager)**:地图事件监听(点击、悬停、移动等)
103
- - **配置管理 (ConfigManager)**:坐标转换、视图控制、配置管理器
104
-
105
- - **⚡ 高级特性**
106
- - **TypeScript 完全支持**:模块化类型定义,更好的开发体验
107
- - **错误处理系统 (ErrorHandler)**:统一的错误处理和日志记录
108
- - **验证工具 (ValidationUtils)**:参数验证和数据校验
109
- - **模块化设计**:支持按需加载和懒加载
110
- - **坐标系支持**:CGCS2000坐标系和投影转换
111
- - **向后兼容**:保持 API 稳定性
112
-
113
- - **🔧 开发友好**
114
- - 支持自定义图层、样式、交互逻辑
115
- - 兼容主流前端框架(Vue、React、Angular)
116
- - 完整的 JSDoc 注释
117
- - 详细的迁移指南
118
- - 丰富的示例代码
119
-
120
- ---
121
-
122
- ## 安装
123
-
124
- ```bash
125
- npm install my-openlayer
126
- #
127
- yarn add my-openlayer
128
- # 或
129
- pnpm add my-openlayer
130
- ```
131
-
132
- ### 依赖要求
133
-
134
- - **OpenLayers**: ^7.0.0 或更高版本
135
- - **proj4**: ^2.8.0 或更高版本
136
- - **@turf/turf**: ^6.5.0 或更高版本(用于高级几何计算)
137
-
138
- ### 环境配置
139
-
140
- 使用天地图服务需要配置API Token:
141
-
142
- ```bash
143
- # 在项目根目录创建 .env 文件(Vite)
144
- VITE_TIANDITU_TOKEN=your_tianditu_token_here
145
-
146
- # 其他可选配置(示例)
147
- VITE_MAP_CENTER_LON=119.81
148
- VITE_MAP_CENTER_LAT=29.969
149
- VITE_MAP_ZOOM=10
150
- ```
151
-
152
- ### 配置选项
153
-
154
- #### 基础配置
155
-
156
- ```javascript
157
- const config = {
158
- target: 'map', // 地图容器ID
159
- center: [119.81, 29.969], // 地图中心点
160
- zoom: 10, // 缩放级别
161
- tiandituToken: process.env.VUE_APP_TIANDITU_TOKEN, // 天地图token(从环境变量获取)
162
- minZoom: 1, // 最小缩放级别
163
- maxZoom: 20, // 最大缩放级别
164
- annotation: true, // 是否显示注记
165
- coordinateSystem: 'EPSG:4326', // 坐标系(默认WGS84,支持CGCS2000)
166
- };
167
- ```
168
-
169
- ---
170
-
171
- ## 快速上手
172
-
173
- ### 1. 初始化地图
174
-
175
- ```typescript
176
- // 方式一:默认导入(推荐)
177
- import MyOl, { MapInitType } from 'my-openlayer';
178
-
179
- // 方式二:命名导入
180
- // import { MyOl, MapInitType } from 'my-openlayer';
181
-
182
- // 地图初始化配置
183
- const mapConfig: MapInitType = {
184
- center: [119.81, 29.969],
185
- zoom: 10,
186
- minZoom: 8,
187
- maxZoom: 20,
188
- token: import.meta.env.VITE_TIANDITU_TOKEN, // 从环境变量获取天地图 token(Vite)
189
- annotation: true,
190
- layers: {
191
- vec_c: [],
192
- img_c: [],
193
- ter_c: []
194
- }
195
- };
196
-
197
- // 创建地图实例
198
- const map = new MyOl('map-container', mapConfig);
199
- ```
200
-
201
- ### 2. 容器 HTML
202
-
203
- ```html
204
- <div id="map-container" style="width: 100vw; height: 100vh;"></div>
205
- ```
206
-
207
- ### 模块获取与使用模式
208
-
209
- ```typescript
210
- // 1) 链式调用(推荐):通过 MyOl 获取模块并直接使用
211
- const myOl = new MyOl('map-container', mapConfig);
212
- myOl.getPoint().addPoint(pointData, { layerName: 'p', textKey: 'name', img: 'marker.png' });
213
- myOl.getLine().addLine(lineGeoJSON, { layerName: 'line', strokeColor: '#037AFF', strokeWidth: 3 });
214
- myOl.getPolygon().addPolygon(zoneGeoJSON, { layerName: 'zone', textKey: 'name', textVisible: true });
215
-
216
- // 2) 独立实例化:直接传入原生 ol.Map 创建模块实例
217
- const olMap = myOl.map; // MyOl 暴露原生 Map 实例
218
- import { Point, Line, Polygon } from 'my-openlayer';
219
-
220
- const point = new Point(olMap);
221
- point.addPoint(pointData, { layerName: 'p', textKey: 'name', img: 'marker.png' });
222
-
223
- const line = new Line(olMap);
224
- line.addLine(lineGeoJSON, { layerName: 'line' });
225
-
226
- const polygon = new Polygon(olMap);
227
- polygon.addPolygon(zoneGeoJSON, { layerName: 'zone', textKey: 'name' });
228
- ```
229
-
230
- ---
231
-
232
- ## 详细用法
233
-
234
- ### 底图管理
235
-
236
- ```javascript
237
- const baseLayers = map.getMapBaseLayers();
238
-
239
- // 切换底图
240
- baseLayers.switchBaseLayer('vec_c');
241
- baseLayers.switchBaseLayer('img_c');
242
- baseLayers.switchBaseLayer('ter_c');
243
-
244
- // 添加注记图层
245
- baseLayers.addAnnotationLayer({
246
- type: 'cva_c',
247
- zIndex: 11,
248
- visible: true
249
- });
250
- ```
251
-
252
- ### 点位操作
253
-
254
- ```typescript
255
- import { PointOptions, ClusterOptions, PointData } from 'my-openlayer';
256
-
257
- const point = map.getPoint();
258
-
259
- // 点位数据
260
- const pointData: PointData[] = [
261
- { lgtd: 119.81, lttd: 29.969, name: '测试点位', type: 'marker' }
262
- ];
263
-
264
- // 添加普通点位
265
- const pointOptions: PointOptions = {
266
- layerName: 'test-point',
267
- textKey: 'name',
268
- img: 'marker.png',
269
- scale: 1.2,
270
- textFont: '12px sans-serif',
271
- textFillColor: '#FFF',
272
- textStrokeColor: '#000',
273
- textStrokeWidth: 3,
274
- textOffsetY: 20,
275
- zIndex: 4,
276
- visible: true
277
- };
278
- point.addPoint(pointData, pointOptions);
279
-
280
- // 添加聚合点位
281
- const clusterData: PointData[] = [
282
- { lgtd: 119.81, lttd: 29.969, name: 'A' },
283
- { lgtd: 119.82, lttd: 29.97, name: 'B' }
284
- ];
285
- const clusterOptions: ClusterOptions = {
286
- layerName: 'cluster-point',
287
- textKey: 'name',
288
- img: 'cluster.png',
289
- distance: 50,
290
- minDistance: 20,
291
- zIndex: 4
292
- };
293
- point.addClusterPoint(clusterData, clusterOptions);
294
-
295
- // 添加 Vue 组件点位
296
- const domPoints = point.addVueTemplatePoint(
297
- [{ lgtd: 119.81, lttd: 29.969 }],
298
- YourVueComponent,
299
- { positioning: 'center-center' }
300
- );
301
-
302
- // 控制组件点位显隐
303
- domPoints.setVisible(true);
304
-
305
- // 移除组件点位
306
- domPoints.remove();
307
-
308
- // 地图定位
309
- point.locationAction(119.81, 29.969, 15, 1000);
310
- ```
311
-
312
- ### 线要素操作
313
-
314
- ```typescript
315
- import { LineOptions, MapJSONData } from 'my-openlayer';
316
-
317
- const line = map.getLine();
318
-
319
- // 线要素数据(GeoJSON 格式)
320
- const lineGeoJSON: MapJSONData = {
321
- type: 'FeatureCollection',
322
- features: [
323
- {
324
- type: 'Feature',
325
- properties: { name: '测试线路', type: 'highway' },
326
- geometry: {
327
- type: 'LineString',
328
- coordinates: [[119.81, 29.969], [119.82, 29.97]]
329
- }
330
- }
331
- ]
332
- };
333
-
334
- // 添加普通线要素
335
- const lineOptions: LineOptions = {
336
- layerName: 'test-line',
337
- type: 'test-line',
338
- strokeColor: '#037AFF',
339
- strokeWidth: 3,
340
- lineDash: [5, 5], // 虚线样式
341
- zIndex: 3,
342
- textVisible: true,
343
- textCallBack: (feature) => feature.get('name')
344
- };
345
- line.addLineCommon(lineGeoJSON, lineOptions);
346
-
347
- // 添加河流要素(支持分级显示)
348
- const riverOptions: LineOptions = {
349
- layerName: 'river',
350
- type: 'river',
351
- strokeColor: '#0071FF',
352
- strokeWidth: 3,
353
- zIndex: 6,
354
- visible: true
355
- };
356
- line.addRiverLayersByZoom(riverGeoJSON, riverOptions);
357
-
358
- // 控制河流图层显隐
359
- line.showRiverLayer(true); // 显示
360
- line.showRiverLayer(false); // 隐藏
361
- ```
362
-
363
- ### 面要素操作
364
-
365
- ```typescript
366
- import MyOl, { PolygonOptions, HeatMapOptions, FeatureColorUpdateOptions, PointData } from 'my-openlayer';
367
-
368
- const polygon = map.getPolygon();
369
-
370
- // 面要素数据(GeoJSON 格式)
371
- const borderGeoJSON: MapJSONData = {
372
- type: 'FeatureCollection',
373
- features: [
374
- {
375
- type: 'Feature',
376
- properties: { name: '边界区域' },
377
- geometry: {
378
- type: 'Polygon',
379
- coordinates: [[[119.8, 29.96], [119.82, 29.96], [119.82, 29.98], [119.8, 29.98], [119.8, 29.96]]]
380
- }
381
- }
382
- ]
383
- };
384
-
385
- // 添加边界面
386
- const borderOptions: PolygonOptions = {
387
- layerName: 'border',
388
- fillColor: 'rgba(255,255,255,0)',
389
- strokeColor: '#EBEEF5',
390
- strokeWidth: 2,
391
- zIndex: 1
392
- };
393
- polygon.addBorderPolygon(borderGeoJSON, borderOptions);
394
-
395
- // 添加分区面
396
- const zoneOptions: PolygonOptions = {
397
- layerName: 'zone',
398
- fillColor: 'rgba(1, 111, 255, 0.3)',
399
- strokeColor: '#037AFF',
400
- strokeWidth: 2,
401
- textVisible: true,
402
- textKey: 'name',
403
- textFont: '14px Calibri,sans-serif',
404
- textFillColor: '#FFF',
405
- textStrokeColor: '#409EFF',
406
- textStrokeWidth: 2,
407
- zIndex: 2
408
- };
409
- polygon.addPolygon(zoneGeoJSON, zoneOptions);
410
-
411
- // 更新面颜色
412
- const colorUpdateOptions: FeatureColorUpdateOptions = {
413
- textKey: 'name'
414
- };
415
- polygon.updateFeatureColor('zone', { 'A区': 'rgba(255,0,0,0.6)' }, colorUpdateOptions);
416
-
417
- // 添加图片图层
418
- const extent = [119.8, 29.96, 119.82, 29.98]; // [minx, miny, maxy]
419
- polygon.addImageLayer({ img: 'img.png', extent }, { layerName: 'imgLayer', zIndex: 10 });
420
-
421
- // 添加热力图
422
- const heatData: PointData[] = [
423
- { lgtd: 119.81, lttd: 29.969, value: 10 },
424
- { lgtd: 119.82, lttd: 29.97, value: 20 }
425
- ];
426
- const heatOptions: HeatMapOptions = {
427
- layerName: 'heatLayer',
428
- valueKey: 'value',
429
- radius: 20,
430
- blur: 15,
431
- opacity: 0.8,
432
- zIndex: 5
433
- };
434
- polygon.addHeatmap('heatLayer', heatData, heatOptions);
435
- ```
436
-
437
- ## 高级功能
438
-
439
- ### 错误处理系统
440
-
441
- ```typescript
442
- import { MyOl, ErrorHandler, ErrorType, MyOpenLayersError } from 'my-openlayer';
443
-
444
- // 获取错误处理器实例
445
- const errorHandler = ErrorHandler.getInstance();
446
-
447
- // 设置全局错误回调
448
- errorHandler.addErrorCallback((error: MyOpenLayersError) => {
449
- console.log('地图错误:', error.message);
450
- console.log('错误类型:', error.type);
451
- console.log('错误详情:', error.details);
452
-
453
- // 发送错误到监控系统
454
- sendToMonitoring({
455
- type: error.type,
456
- message: error.message,
457
- timestamp: new Date().toISOString()
458
- });
459
- });
460
-
461
- // 手动验证和错误处理
462
- try {
463
- // 验证坐标
464
- ErrorHandler.validateCoordinates(longitude, latitude);
465
-
466
- // 验证图层名称
467
- ErrorHandler.validateLayerName(layerName);
468
-
469
- // 验证颜色格式
470
- ErrorHandler.validateColor(color);
471
-
472
- } catch (error) {
473
- if (error instanceof MyOpenLayersError) {
474
- console.error(`${error.type}错误:`, error.message);
475
- }
476
- }
477
-
478
- // 错误类型
479
- // ErrorType.COORDINATE_ERROR - 坐标错误
480
- // ErrorType.LAYER_ERROR - 图层错误
481
- // ErrorType.STYLE_ERROR - 样式错误
482
- // ErrorType.DATA_ERROR - 数据错误
483
- // ErrorType.CONFIG_ERROR - 配置错误
484
- ```
485
-
486
- ### 事件管理系统
487
-
488
- ```typescript
489
- import { MapEventType, EventCallback, MapEventData } from 'my-openlayer';
490
-
491
- // 获取事件管理器
492
- const eventManager = map.getEventManager();
493
-
494
- // 监听点击事件
495
- const clickCallback: EventCallback = (eventData: MapEventData) => {
496
- console.log('点击位置:', eventData.coordinate);
497
- console.log('点击要素:', eventData.feature);
498
- console.log('像素位置:', eventData.pixel);
499
- };
500
- const clickListenerId = eventManager.on('click', clickCallback);
501
-
502
- // 监听缩放事件
503
- eventManager.on('zoomend', (eventData) => {
504
- console.log('当前缩放级别:', eventData.zoom);
505
- console.log('地图范围:', eventData.extent);
506
- });
507
-
508
- // 监听鼠标悬停事件
509
- eventManager.on('pointermove', (eventData) => {
510
- if (eventData.feature) {
511
- console.log('悬停要素:', eventData.feature.get('name'));
512
- }
513
- });
514
-
515
- // 移除特定事件监听
516
- eventManager.off(clickListenerId);
517
-
518
- // 移除所有事件监听
519
- eventManager.removeAllListeners();
520
-
521
- // 一次性事件监听
522
- eventManager.on('click', (eventData) => {
523
- console.log('只触发一次');
524
- }, { once: true });
525
-
526
- // 带过滤器的事件监听
527
- eventManager.on('click', (eventData) => {
528
- console.log('点击了要素');
529
- }, {
530
- filter: (eventData) => eventData.feature !== undefined
531
- });
532
-
533
- // 事件统计
534
- console.log('点击事件监听器数量:', eventManager.getListenerCount('click'));
535
- console.log('总事件触发次数:', eventManager.getTotalEventCount());
536
- ```
537
-
538
- ### 配置管理系统
539
-
540
- ```typescript
541
- import { MyOl, ConfigManager, PointOptions, LineOptions } from 'my-openlayer';
542
-
543
- // 使用默认配置
544
- const pointOptions: PointOptions = ConfigManager.mergeOptions(
545
- ConfigManager.DEFAULT_POINT_OPTIONS,
546
- {
547
- strokeColor: '#ff0000',
548
- scale: 1.5,
549
- textVisible: true
550
- }
551
- );
552
-
553
- // 获取默认配置
554
- const defaultPointConfig = ConfigManager.DEFAULT_POINT_OPTIONS;
555
- const defaultLineConfig = ConfigManager.DEFAULT_LINE_OPTIONS;
556
- const defaultPolygonConfig = ConfigManager.DEFAULT_POLYGON_OPTIONS;
557
-
558
- // 验证工具
559
- if (ConfigManager.isValidCoordinate(lng, lat)) {
560
- console.log('坐标有效');
561
- }
562
-
563
- if (ConfigManager.isValidColor('#ff0000')) {
564
- console.log('颜色格式有效');
565
- }
566
-
567
- if (ConfigManager.isValidZIndex(10)) {
568
- console.log('层级有效');
569
- }
570
-
571
- // 生成唯一ID
572
- const layerId = ConfigManager.generateId('layer'); // layer_1234567890
573
- const pointId = ConfigManager.generateId('point'); // point_1234567890
574
-
575
- // 深度合并配置
576
- const mergedConfig = ConfigManager.mergeOptions(
577
- { a: 1, b: { c: 2 } },
578
- { b: { d: 3 }, e: 4 }
579
- ); // { a: 1, b: { c: 2, d: 3 }, e: 4 }
580
- ```
581
-
582
- ### 地图工具
583
-
584
- ```javascript
585
- const tools = map.getTools();
586
-
587
- // 获取图层
588
- const layer = tools.getLayerByLayerName('layerName');
589
-
590
- // 移除图层
591
- tools.removeLayer('layerName');
592
-
593
- // 设置图层可见性
594
- tools.setLayerVisible('layerName', true);
595
-
596
- // 事件监听(使用 EventManager)
597
- const em = map.getEventManager();
598
- em.on('click', (eventData) => {
599
- console.log('点击要素:', eventData.feature);
600
- });
601
- ```
602
-
603
- ### 测量工具
604
-
605
- ```javascript
606
- import { MyOl, MeasureHandler } from 'my-openlayer';
607
- const measure = new MeasureHandler(map.map); // 传入原生 ol.Map
608
- measure.start('Polygon'); // 开始绘制多边形测量
609
- // measure.start('LineString'); // 开始绘制线测量
610
- // 结束测量
611
- measure.end();
612
- // 清除所有测量结果
613
- measure.clean();
614
- // 销毁测量工具
615
- measure.destory();
616
- ```
617
-
618
- ---
619
-
620
- ## API 文档与示例
621
-
622
- ### MyOl
623
-
624
- #### 构造函数
625
-
626
- ```typescript
627
- new MyOl(id: string, options: MapInitType)
628
- ```
629
-
630
- **参数说明:**
631
-
632
- - `id`: 地图容器的 DOM 元素 ID
633
- - `options`: 地图初始化配置对象
634
- - `center`: 地图中心点坐标 `[longitude, latitude]`
635
- - `zoom`: 初始缩放级别
636
- - `token`: 天地图 API Token(建议从环境变量获取)
637
- - `minZoom`: 最小缩放级别(可选,默认:1)
638
- - `maxZoom`: 最大缩放级别(可选,默认:20)
639
- - `annotation`: 是否显示注记图层(可选,默认:true)
640
- - `layers`: 图层配置(可选)
641
- - `extent`: 地图范围限制(可选)
642
- - `mapClipData`: 地图裁剪数据(可选)
643
-
644
- #### 方法
645
-
646
- - **getPoint()**
647
- > 获取点位操作实例。
648
- ```javascript
649
- const point = map.getPoint();
650
- ```
651
-
652
- - **getLine()**
653
- > 获取线要素操作实例。
654
- ```javascript
655
- const line = map.getLine();
656
- ```
657
-
658
- - **getPolygon()**
659
- > 获取面要素操作实例。
660
- ```javascript
661
- const polygon = map.getPolygon();
662
- ```
663
-
664
- - **getTools()**
665
- > 获取地图工具实例,提供图层管理、事件监听等功能。
666
- ```javascript
667
- const tools = map.getTools();
668
- ```
669
-
670
- - **getMapBaseLayers()**
671
- > 获取底图图层管理实例,用于底图切换和管理。
672
- ```javascript
673
- const baseLayers = map.getMapBaseLayers();
674
- ```
675
-
676
- - **getEventManager()**
677
- > 获取事件管理器实例,用于统一的事件监听和管理。
678
- ```javascript
679
- const eventManager = map.getEventManager();
680
- ```
681
-
682
- - **getConfigManager()**
683
- > 获取配置管理器实例,用于配置验证和管理。
684
- ```javascript
685
- const configManager = map.getConfigManager();
686
- ```
687
-
688
- - 不直接暴露原生地图实例;推荐通过模块实例(如 `MapTools`)与 `EventManager` 完成操作
689
-
690
- - **resetPosition(duration?: number)**
691
- > 重置地图位置。
692
- ```javascript
693
- map.resetPosition(1000); // 1秒动画重置
694
- ```
695
-
696
- - **locationAction(lgtd: number, lttd: number, zoom?: number, duration?: number)**
697
- > 地图定位到指定点。
698
- ```javascript
699
- map.locationAction(119.81, 29.969, 15, 1000);
700
- ```
701
-
702
- // 事件监听:使用 EventManager 统一管理
703
- // const eventManager = map.getEventManager();
704
- // eventManager.on('click', (eventData) => { ... })
705
-
706
- ---
707
-
708
- ### MapBaseLayers
709
-
710
- - **switchBaseLayer(type: TiandituType)**
711
- > 切换底图类型,自动处理注记图层。
712
- ```javascript
713
- baseLayers.switchBaseLayer('img_c');
714
- ```
715
-
716
- - **addAnnotationLayer(options: AnnotationLayerOptions)**
717
- > 添加注记图层。
718
- ```javascript
719
- baseLayers.addAnnotationLayer({
720
- type: 'cva_c',
721
- zIndex: 11,
722
- visible: true
723
- });
724
- ```
725
-
726
- - **toggleAnnotation(show?: boolean)**
727
- > 切换注记图层显示状态。
728
- ```javascript
729
- baseLayers.toggleAnnotation(true); // 显示注记
730
- baseLayers.toggleAnnotation(false); // 隐藏注记
731
- ```
732
-
733
- - **getCurrentBaseLayer()**
734
- > 获取当前底图类型。
735
- ```javascript
736
- const currentType = baseLayers.getCurrentBaseLayer();
737
- ```
738
-
739
- - **initLayer()**
740
- > 初始化底图图层。
741
- ```javascript
742
- baseLayers.initLayer();
743
- ```
744
-
745
- ---
746
-
747
- ### Point
748
-
749
- - **addPoint(pointData: PointData[], options: PointOptions)**
750
- > 添加普通点位到指定图层,支持文本与图标样式。
751
- ```javascript
752
- point.addPoint([
753
- { lgtd: 119.81, lttd: 29.969, name: '测试点位' }
754
- ], {
755
- layerName: 'test-point',
756
- textKey: 'name',
757
- img: 'marker.png'
758
- });
759
- ```
760
-
761
- - **addClusterPoint(pointData: PointData[], options: ClusterOptions)**
762
- > 添加聚合点位,自动根据缩放级别聚合显示。
763
- ```javascript
764
- point.addClusterPoint([
765
- { lgtd: 119.81, lttd: 29.969, name: 'A' },
766
- { lgtd: 119.82, lttd: 29.97, name: 'B' }
767
- ], {
768
- layerName: 'cluster-point',
769
- textKey: 'name',
770
- img: 'cluster.png',
771
- zIndex: 4
772
- });
773
- ```
774
-
775
- - **addVueTemplatePoint(pointDataList: PointData[], template: any, options?)**
776
- > 添加 Vue 组件点位。
777
- ```javascript
778
- const domPoints = point.addVueTemplatePoint(
779
- [{ lgtd: 119.81, lttd: 29.969 }],
780
- YourVueComponent,
781
- { positioning: 'center-center' }
782
- );
783
- domPoints.setVisible(true);
784
- domPoints.remove();
785
- ```
786
-
787
- - **addTwinkleLayer(twinkleList: any[], className?: string, key: string, callback?)**
788
- > 添加闪烁点覆盖物。
789
-
790
- - **locationAction(lgtd: number, lttd: number, zoom?: number, duration?: number)**
791
- > 地图定位。
792
- ```javascript
793
- point.locationAction(119.81, 29.969, 15, 1000);
794
- ```
795
-
796
- ---
797
-
798
- ### Line
799
-
800
- - **addLineCommon(data: MapJSONData, options: OptionsType)**
801
- > 添加普通线要素。
802
- ```javascript
803
- line.addLineCommon(lineGeoJSON, {
804
- layerName: 'test-line',
805
- type: 'test-line',
806
- strokeColor: '#037AFF',
807
- strokeWidth: 3
808
- });
809
- ```
810
-
811
- - **addRiverLayersByZoom(data: MapJSONData, options: OptionsType)**
812
- > 添加河流要素(分级显示)。
813
- ```javascript
814
- line.addRiverLayersByZoom(riverGeoJSON, {
815
- layerName: 'river',
816
- type: 'river',
817
- strokeColor: '#0071FF',
818
- strokeWidth: 3,
819
- zIndex: 6,
820
- visible: true
821
- });
822
- ```
823
-
824
- - **showRiverLayer(show: boolean)**
825
- > 控制河流图层显隐。
826
- ```javascript
827
- line.showRiverLayer(true); // 显示
828
- line.showRiverLayer(false); // 隐藏
829
- ```
830
-
831
- ---
832
-
833
- ### Polygon
834
-
835
- - **addBorderPolygon(data: MapJSONData, options?: OptionsType)**
836
- > 添加边界面。
837
- ```javascript
838
- polygon.addBorderPolygon(borderGeoJSON, {
839
- layerName: 'border',
840
- fillColor: 'rgba(255,255,255,0)',
841
- strokeColor: '#EBEEF5',
842
- strokeWidth: 2
843
- });
844
- ```
845
-
846
- - **addPolygon(data: MapJSONData, options?: OptionsType)**
847
- > 添加分区面。
848
- ```javascript
849
- polygon.addPolygon(zoneGeoJSON, {
850
- layerName: 'zone',
851
- fillColor: 'rgba(1, 111, 255, 0.3)',
852
- strokeColor: '#037AFF',
853
- strokeWidth: 2,
854
- textVisible: true,
855
- textKey: 'name',
856
- textFont: '14px Calibri,sans-serif',
857
- textFillColor: '#FFF',
858
- textStrokeColor: '#409EFF',
859
- textStrokeWidth: 2
860
- });
861
- ```
862
-
863
- - **updateFeatureColor(layerName: string, colorObj?: { [propName: string]: string }, options?: FeatureColorUpdateOptions)**
864
- > 更新面颜色。
865
- ```javascript
866
- polygon.updateFeatureColor('zone', { 'A区': 'rgba(255,0,0,0.6)' }, { textKey: 'name' });
867
- ```
868
-
869
- - **addImageLayer(imageData: ImageLayerData, options?: PolygonOptions)**
870
- > 添加图片图层。
871
- ```javascript
872
- polygon.addImageLayer({ img: 'img.png', extent: [minx, miny, maxx, maxy] }, { layerName: 'imgLayer', zIndex: 10 });
873
- ```
874
-
875
- - **addHeatmap(layerName: string, pointData: PointData[], options: HeatMapOptions)**
876
- > 添加热力图。
877
- ```javascript
878
- polygon.addHeatmap('heatLayer', [
879
- { lgtd: 119.81, lttd: 29.969, value: 10 },
880
- { lgtd: 119.82, lttd: 29.97, value: 20 }
881
- ], {
882
- valueKey: 'value',
883
- radius: 20,
884
- blur: 15
885
- });
886
- ```
887
-
888
- - **removePolygonLayer(layerName: string)**
889
- > 移除面图层。
890
- ```javascript
891
- polygon.removePolygonLayer('zone');
892
- ```
893
-
894
- ---
895
-
896
- ### MapTools
897
-
898
- - **getLayerByLayerName(layerName: string)**
899
- > 获取图层。
900
- ```javascript
901
- const layer = tools.getLayerByLayerName('myLayer');
902
- ```
903
-
904
- - **removeLayer(layerName: string)**
905
- > 移除图层。
906
- ```javascript
907
- tools.removeLayer('myLayer');
908
- ```
909
-
910
- - **setLayerVisible(layerName: string, visible: boolean)**
911
- > 设置图层可见性。
912
- ```javascript
913
- tools.setLayerVisible('myLayer', true);
914
- ```
915
-
916
- // 事件监听请使用 EventManager:
917
- // const em = map.getEventManager();
918
- // em.on('click', (eventData) => { console.log(eventData.feature) })
919
-
920
- - **static setMapClip(baseLayer: any, data: MapJSONData)**
921
- > 设置地图裁剪。
922
- ```javascript
923
- MapTools.setMapClip(baseLayer, clipGeoJSON);
924
- ```
925
-
926
- ---
927
-
928
- ### MeasureHandler
929
-
930
- 测量工具类,提供距离和面积测量功能,支持实时测量显示。
931
-
932
- - **start(type: 'Polygon' | 'LineString')**
933
- > 开始测量,支持距离和面积测量。
934
- ```javascript
935
- measure.start('Polygon'); // 面积测量
936
- measure.start('LineString'); // 距离测量
937
- ```
938
-
939
- - **end()**
940
- > 结束当前测量操作。
941
- ```javascript
942
- measure.end();
943
- ```
944
-
945
- - **clean()**
946
- > 清除所有测量结果和图形。
947
- ```javascript
948
- measure.clean();
949
- ```
950
-
951
- - **destory()**
952
- > 销毁测量工具,释放资源。
953
- ```javascript
954
- measure.destory();
955
- ```
956
-
957
- ### ErrorHandler
958
-
959
- 错误处理工具类,提供统一的错误处理和日志记录。
960
-
961
- - **getInstance()**
962
- > 获取错误处理器单例实例。
963
- ```javascript
964
- const errorHandler = ErrorHandler.getInstance();
965
- ```
966
-
967
- - **handleError(error: MyOpenLayersError)**
968
- > 处理错误,记录日志并触发回调。
969
- ```javascript
970
- errorHandler.handleError(error);
971
- ```
972
-
973
- - **validate(condition: boolean, message: string, context?: any)**
974
- > 验证条件,失败时抛出错误。
975
- ```javascript
976
- ErrorHandler.validate(isValid, '验证失败', { data });
977
- ```
978
-
979
- ### ValidationUtils
980
-
981
- 验证工具类,提供各种数据验证方法。
982
-
983
- - **isValidCoordinate(longitude: number, latitude: number)**
984
- > 验证坐标是否有效。
985
- ```javascript
986
- const isValid = ValidationUtils.isValidCoordinate(119.81, 29.969);
987
- ```
988
-
989
- - **validateMapInstance(map: any)**
990
- > 验证地图实例。
991
- ```javascript
992
- ValidationUtils.validateMapInstance(map);
993
- ```
994
-
995
- - **validateLayerName(layerName: string)**
996
- > 验证图层名称。
997
- ```javascript
998
- ValidationUtils.validateLayerName('myLayer');
999
- ```
1000
-
1001
- ---
1002
-
1003
- ## 类型定义
1004
-
1005
- 本库提供完整的 TypeScript 类型定义,采用模块化设计,详见 [src/types.ts](src/types.ts)。
1006
-
1007
- ### 核心类型
1008
-
1009
- ```typescript
1010
- // 地图初始化配置
1011
- interface MapInitType {
1012
- layers?: BaseLayer[] | { [key: string]: BaseLayer[] },
1013
- zoom?: number,
1014
- center?: number[],
1015
- minZoom?: number,
1016
- maxZoom?: number,
1017
- extent?: number[],
1018
- mapClipData?: MapJSONData,
1019
- token?: string,
1020
- annotation?: boolean,
1021
- coordinateSystem?: string // 坐标系(支持CGCS2000)
1022
- }
1023
-
1024
- // 点位数据
1025
- interface PointData {
1026
- lgtd: number, // 经度
1027
- lttd: number, // 纬度
1028
- [key: string]: any // 其他属性
1029
- }
1030
-
1031
- // GeoJSON 数据
1032
- interface MapJSONData {
1033
- type: string,
1034
- name?: string,
1035
- features: Feature[]
1036
- }
1037
-
1038
- // 事件类型
1039
- type EventType = 'click' | 'hover' | 'moveend';
1040
-
1041
- // 天地图类型
1042
- type TiandituType = 'vec_c' | 'img_c' | 'ter_c' | string;
1043
- ```
1044
-
1045
- ### 模块化选项接口
1046
-
1047
- ```typescript
1048
- // 基础选项 - 所有图层的公共配置
1049
- interface BaseOptions {
1050
- /** 图层名称 */
1051
- layerName?: string;
1052
- /** 图层层级 */
1053
- zIndex?: number;
1054
- /** 图层可见性 */
1055
- visible?: boolean;
1056
- /** 图层透明度 */
1057
- opacity?: number;
1058
- /** 是否适应视图 */
1059
- fitView?: boolean;
1060
- // ... 其他基础属性
1061
- }
1062
-
1063
- // 样式选项 - 图形样式相关配置
1064
- interface StyleOptions {
1065
- /** 描边颜色 */
1066
- strokeColor?: string | number[];
1067
- /** 描边宽度 */
1068
- strokeWidth?: number;
1069
- /** 线条虚线样式 */
1070
- lineDash?: number[];
1071
- /** 填充颜色 */
1072
- fillColor?: string;
1073
- // ... 其他样式属性
1074
- }
1075
-
1076
- // 文本选项 - 文本标注相关配置
1077
- interface TextOptions {
1078
- /** 文本可见性 */
1079
- textVisible?: boolean;
1080
- /** 文本内容回调函数 */
1081
- textCallBack?: (feature: any) => string;
1082
- /** 文本字体 */
1083
- textFont?: string;
1084
- /** 文本填充颜色 */
1085
- textFillColor?: string;
1086
- // ... 其他文本属性
1087
- }
1088
-
1089
- // 点位选项 - 点位图层专用配置
1090
- interface PointOptions extends BaseOptions, StyleOptions, TextOptions {
1091
- /** 文本字段键 */
1092
- textKey?: string;
1093
- /** 图标图片 */
1094
- img?: string;
1095
- /** 图标缩放比例 */
1096
- scale?: number;
1097
- /** 图标颜色 */
1098
- iconColor?: string;
1099
- }
1100
-
1101
- // 线条选项 - 线条图层专用配置
1102
- interface LineOptions extends BaseOptions, StyleOptions, TextOptions {
1103
- /** 线条类型 */
1104
- type?: string;
1105
- }
1106
-
1107
- // 多边形选项 - 多边形图层专用配置
1108
- interface PolygonOptions extends BaseOptions, StyleOptions, TextOptions {
1109
- /** 文本字段键 */
1110
- textKey?: string;
1111
- /** 是否为蒙版 */
1112
- mask?: boolean;
1113
- }
1114
-
1115
- // 聚合选项 - 聚合点位专用配置
1116
- interface ClusterOptions extends PointOptions {
1117
- /** 聚合距离 */
1118
- distance?: number;
1119
- /** 最小聚合距离 */
1120
- minDistance?: number;
1121
- }
1122
-
1123
- // 热力图选项
1124
- interface HeatMapOptions {
1125
- layerName?: string,
1126
- radius?: number,
1127
- blur?: number,
1128
- gradient?: string[],
1129
- opacity?: number,
1130
- visible?: boolean,
1131
- zIndex?: number,
1132
- valueKey?: string,
1133
- }
1134
- ```
1135
-
1136
- ### VueTemplatePointOptions
1137
-
1138
- Vue 组件点位配置类型,支持 Vue 2 和 Vue 3。
1139
-
1140
- ```typescript
1141
- interface VueTemplatePointOptions {
1142
- coordinate: [number, number]; // 点位坐标
1143
- template: any; // Vue 组件模板
1144
- data?: any; // 传递给组件的数据
1145
- vue: VueInstance | VueApp; // Vue 实例(Vue 2/3)
1146
- layerName?: string; // 图层名称
1147
- id?: string; // 点位唯一标识
1148
- className?: string; // CSS 类名
1149
- stopEvent?: boolean; // 是否阻止事件冒泡
1150
- }
1151
- ```
1152
-
1153
- ### ErrorType
1154
-
1155
- 错误类型枚举。
1156
-
1157
- ```typescript
1158
- enum ErrorType {
1159
- VALIDATION_ERROR = 'VALIDATION_ERROR',
1160
- MAP_ERROR = 'MAP_ERROR',
1161
- LAYER_ERROR = 'LAYER_ERROR',
1162
- COORDINATE_ERROR = 'COORDINATE_ERROR',
1163
- DATA_ERROR = 'DATA_ERROR',
1164
- COMPONENT_ERROR = 'COMPONENT_ERROR'
1165
- }
1166
- ```
1167
-
1168
- ### MyOpenLayersError
1169
-
1170
- 自定义错误类。
1171
-
1172
- ```typescript
1173
- class MyOpenLayersError extends Error {
1174
- public readonly type: ErrorType;
1175
- public readonly timestamp: Date;
1176
- public readonly context?: any;
1177
- }
1178
- ```
1179
-
1180
- ### 兼容性类型
1181
-
1182
- ```typescript
1183
- /**
1184
- * 兼容性类型别名 - 保持向后兼容
1185
- * @deprecated 请使用具体的选项接口:PointOptions, LineOptions, PolygonOptions
1186
- */
1187
- type OptionsType = BaseOptions & StyleOptions & TextOptions & {
1188
- textKey?: string;
1189
- img?: string;
1190
- scale?: number;
1191
- iconColor?: string;
1192
- type?: string;
1193
- mask?: boolean;
1194
- };
1195
- ```
1196
-
1197
- ## 迁移指南
1198
-
1199
- ### 快速迁移示例
1200
-
1201
- ```typescript
1202
- // 旧写法
1203
- import { MyOl, OptionsType } from 'my-openlayer';
1204
- const options: OptionsType = {
1205
- layerName: 'points',
1206
- strokeColor: '#ff0000',
1207
- img: '/icons/marker.png'
1208
- };
1209
-
1210
- // 新写法
1211
- import { MyOl, PointOptions } from 'my-openlayer';
1212
- const options: PointOptions = {
1213
- layerName: 'points',
1214
- strokeColor: '#ff0000',
1215
- img: '/icons/marker.png'
1216
- };
1217
- ```
1218
-
1219
- ### 迁移优势
1220
-
1221
- - **类型安全**:更精确的类型检查
1222
- - **代码提示**:更好的 IDE 支持
1223
- - **可维护性**:清晰的模块化结构
1224
- - **向后兼容**:保留 `OptionsType` 作为兼容性类型
1225
-
1226
- ---
1227
-
1228
- ## 依赖
1229
-
1230
- ### 运行时依赖
1231
-
1232
- - **ol**: ^10.6.1 - OpenLayers 地图库
1233
- - **proj4**: ^2.7.5 - 坐标系转换库
1234
- - **@turf/turf**: ^7.2.0 - 地理空间分析库
1235
-
1236
- ### 开发依赖
1237
-
1238
- - **typescript**: ~5.6.2 - TypeScript 编译器
1239
- - **vite**: ^5.4.10 - 构建工具
1240
- - **@vitejs/plugin-vue**: ^5.0.4 - Vue 插件支持
1241
- - **vue-tsc**: ^2.0.6 - Vue 类型检查
1242
-
1243
- ### 对等依赖
1244
-
1245
- - 无强制对等依赖;推荐 `ol` 与库版本保持一致(^10.6.1)。
1246
-
1247
- ---
1248
-
1249
- ## 贡献指南
1250
-
1251
- 欢迎提交 Issue 或 Pull Request!
1252
-
1253
- 1. Fork 本仓库
1254
- 2. 新建分支:`git checkout -b feature/your-feature`
1255
- 3. 提交更改:`git commit -m 'feat: 新功能描述'`
1256
- 4. 推送分支:`git push origin feature/your-feature`
1257
- 5. 提交 Pull Request
1258
-
1259
- ---
1260
-
1261
- ## 常见问题
1262
-
1263
- ### 基础配置
1264
-
1265
- **Q: 如何获取天地图 token?**
1266
-
1267
- A: 访问 [天地图开发者平台](https://lbs.tianditu.gov.cn/) 注册账号并申请密钥(token)。申请后在初始化地图时传入 `token` 参数。
1268
-
1269
- **Q: 为什么地图无法加载?**
1270
-
1271
- A: 请检查以下几点:
1272
- - 天地图 token 是否正确且有效
1273
- - 网络连接是否正常
1274
- - 坐标系是否正确(默认使用 EPSG:4326)
1275
- - 容器元素是否存在且有正确的尺寸
1276
-
1277
- ### 类型和开发
1278
-
1279
- **Q: 如何从旧版本迁移到新的类型系统?**
1280
-
1281
- A: 参考 [迁移指南](MIGRATION_GUIDE.md),主要是将 `OptionsType` 替换为具体的类型接口如 `PointOptions`、`LineOptions` 等。
1282
-
1283
- **Q: TypeScript 报错怎么办?**
1284
-
1285
- A:
1286
- - 确保安装了正确的类型定义包
1287
- - 使用具体的类型接口而不是通用的 `OptionsType`
1288
- - 检查导入语句是否正确
1289
-
1290
- ### 功能使用
1291
-
1292
- **Q: 如何自定义点位样式?**
1293
-
1294
- A: 通过 `PointOptions` 配置样式:
1295
- ```typescript
1296
- const options: PointOptions = {
1297
- img: '/path/to/icon.png',
1298
- scale: 1.2,
1299
- strokeColor: '#ff0000',
1300
- textVisible: true
1301
- };
1302
- ```
1303
-
1304
- **Q: 如何监听地图事件?**
1305
-
1306
- A: 使用 `EventManager`:
1307
- ```typescript
1308
- const eventManager = map.getEventManager();
1309
- eventManager.on('click', (eventData) => {
1310
- console.log('点击位置:', eventData.coordinate);
1311
- });
1312
- ```
1313
-
1314
- **Q: 如何处理错误?**
1315
-
1316
- A: 使用 `ErrorHandler` 进行错误处理:
1317
- ```typescript
1318
- import { MyOl, ErrorHandler } from 'my-openlayer';
1319
-
1320
- // 设置全局错误回调
1321
- ErrorHandler.getInstance().addErrorCallback((error) => {
1322
- console.error('地图错误:', error.message);
1323
- });
1324
-
1325
- // 手动验证
1326
- try {
1327
- ErrorHandler.validateCoordinates(lng, lat);
1328
- } catch (error) {
1329
- console.error('坐标验证失败:', error.message);
1330
- }
1331
- ```
1332
-
1333
- ### 框架集成
1334
-
1335
- **Q: 如何在 Vue 中使用?**
1336
-
1337
- A: 在组件生命周期中初始化和销毁:
1338
- ```vue
1339
- <template>
1340
- <div id="map-container" style="width: 100%; height: 400px;"></div>
1341
- </template>
1342
-
1343
- <script setup>
1344
- import { onMounted, onUnmounted } from 'vue';
1345
- import { MyOl } from 'my-openlayer';
1346
-
1347
- let map = null;
1348
-
1349
- onMounted(() => {
1350
- map = new MyOl('map-container', {
1351
- center: [119.81, 29.969],
1352
- zoom: 10,
1353
- token: 'your-token'
1354
- });
1355
- });
1356
-
1357
- onUnmounted(() => {
1358
- if (map) {
1359
- map.map.dispose();
1360
- }
1361
- });
1362
- </script>
1363
- ```
1364
-
1365
- **Q: 如何在 React 中使用?**
1366
-
1367
- A: 使用 useEffect 钩子:
1368
- ```jsx
1369
- import React, { useEffect, useRef } from 'react';
1370
- import MyOl from 'my-openlayer';
1371
-
1372
- function MapComponent() {
1373
- const mapRef = useRef(null);
1374
- const containerRef = useRef(null);
1375
-
1376
- useEffect(() => {
1377
- if (containerRef.current) {
1378
- mapRef.current = new MyOl(containerRef.current, {
1379
- center: [119.81, 29.969],
1380
- zoom: 10,
1381
- token: 'your-token'
1382
- });
1383
- }
1384
-
1385
- return () => {
1386
- if (mapRef.current) {
1387
- mapRef.current.map.dispose();
1388
- }
1389
- };
1390
- }, []);
1391
-
1392
- return <div ref={containerRef} style={{ width: '100%', height: '400px' }} />;
1393
- }
1394
- ```
1395
-
1396
- ### 性能优化
1397
-
1398
- **Q: 如何优化大量点位的性能?**
1399
-
1400
- A:
1401
- - 使用聚合功能:`addClusterPoint`
1402
- - 设置合适的 `distance` 和 `minDistance` 参数
1403
- - 考虑使用分层加载或虚拟化技术
1404
-
1405
- **Q: 如何减少内存占用?**
1406
-
1407
- A:
1408
- - 及时移除不需要的图层:`tools.removeLayer(layerName)`
1409
- - 使用事件管理器的 `removeAllListeners()` 清理事件监听
1410
- - 在组件销毁时调用 `map.dispose()`
1411
-
1412
- ---
1413
-
1414
- ## 许可证
1415
-
1416
- [MIT](LICENSE)
1417
-
1418
- ---
1419
-
1420
- ## 联系方式
1421
-
1422
- 如有问题或建议,欢迎通过以下方式联系:
1423
-
1424
- - 📧 **邮箱**: 2364184627@qq.com
1425
- - 🐛 **问题反馈**: [GitHub Issues](https://github.com/cuteyuchen/my-openlayer/issues)
1426
- - 💡 **功能建议**: [GitHub Discussions](https://github.com/cuteyuchen/my-openlayer/discussions)
1427
- - 📖 **文档**: [在线文档](https://github.com/cuteyuchen/my-openlayer/blob/main/README.md)
1428
-
1429
- ## 相关资源
1430
-
1431
- - 🌐 **OpenLayers 官网**: [https://openlayers.org/](https://openlayers.org/)
1432
- - 🗺️ **天地图开发者平台**: [https://lbs.tianditu.gov.cn/](https://lbs.tianditu.gov.cn/)
1433
- - 📚 **TypeScript 文档**: [https://www.typescriptlang.org/](https://www.typescriptlang.org/)
1434
- - 🛠️ **Vite 构建工具**: [https://vitejs.dev/](https://vitejs.dev/)
1435
-
1436
- ## 更新日志
1437
-
1438
- ### v1.0.15 (2025-08-20)
1439
-
1440
- #### 新增功能
1441
- - ✨ 完整的 TypeScript 支持和类型定义
1442
- - ✨ 模块化架构设计,支持按需引入
1443
- - ✨ 天地图底图支持(矢量、影像、地形)
1444
- - ✨ 点要素操作(普通点位、聚合点位、闪烁点位)
1445
- - ✨ Vue 组件集成支持(Vue 2/3 兼容)
1446
- - ✨ 线要素和面要素绘制
1447
- - ✨ 热力图和图片图层支持
1448
- - ✨ 测量工具(距离、面积)
1449
- - ✨ 事件管理和配置管理系统
1450
- - ✨ 错误处理和验证工具
1451
- - ✨ CGCS2000 坐标系支持
1452
-
1453
- #### 技术特性
1454
- - 🔧 支持 Vue 2 和 Vue 3
1455
- - 🔧 完整的 TypeScript 类型定义
1456
- - 🔧 模块化设计,懒加载支持
1457
- - 🔧 统一的错误处理机制
1458
- - 🔧 向后兼容性保证
1459
- - 🔧 环境变量配置支持
1460
-
1461
- #### 核心类库
1462
- - 📦 MyOl - 地图核心管理类
1463
- - 📦 MapBaseLayers - 底图管理
1464
- - 📦 Point/Line/Polygon - 要素操作
1465
- - 📦 VueTemplatePoint - Vue 组件支持
1466
- - 📦 MapTools - 地图工具集
1467
- - 📦 MeasureHandler - 测量工具
1468
- - 📦 EventManager - 事件管理
1469
- - 📦 ConfigManager - 配置管理
1470
- - 📦 ErrorHandler - 错误处理
1471
- - 📦 ValidationUtils - 验证工具
1472
-
1473
- #### 文档
1474
- - 📚 完整的 API 文档和类型定义
1475
- - 📚 详细的使用示例和最佳实践
1476
- - 📚 环境配置和部署指南
1477
- - 📚 FAQ 和常见问题解决方案
1478
-
1479
- 查看完整的 [更新日志](CHANGELOG.md)
1480
-
1481
- ---
1482
-
1483
- ## 致谢
1484
-
1485
- 感谢以下开源项目的支持:
1486
-
1487
- - [OpenLayers](https://openlayers.org/) - 强大的地图库
1488
- - [TypeScript](https://www.typescriptlang.org/) - 类型安全的 JavaScript
1489
- - [Vite](https://vitejs.dev/) - 快速的构建工具
1490
-
1491
- ---
1492
-
1493
- <div align="center">
1494
-
1495
- **⭐ 如果这个项目对您有帮助,请给我们一个 Star!⭐**
1496
-
1497
- [![GitHub stars](https://img.shields.io/github/stars/cuteyuchen/my-openlayer.svg?style=social&label=Star)](https://github.com/cuteyuchen/my-openlayer)
1498
- [![GitHub forks](https://img.shields.io/github/forks/cuteyuchen/my-openlayer.svg?style=social&label=Fork)](https://github.com/cuteyuchen/my-openlayer/fork)
1499
-
1500
- **本项目长期维护,欢迎 Star、Fork 和贡献代码!**
1501
-
1502
- </div>
1
+ # my-openlayer
2
+
3
+ my-openlayer 是一个基于 [OpenLayers](https://openlayers.org/) 的现代地图组件库,专为 Web GIS 应用开发者设计。提供完整的 TypeScript 支持、模块化的类型定义、强大的错误处理和事件管理系统,支持天地图底图加载、要素绘制、图层管理、事件监听等丰富功能,极大提升地图开发效率。
4
+
5
+ [![npm version](https://img.shields.io/npm/v/my-openlayer.svg)](https://www.npmjs.com/package/my-openlayer)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ---
10
+
11
+ ## 项目概述
12
+
13
+ - **项目名称**:`my-openlayer`
14
+ - **用途**:基于 OpenLayers 的 TypeScript 地图组件库,提供点/线/面要素、底图切换、热力图、事件与配置管理等能力。
15
+ - **目标用户**:Web GIS 开发者、可视化工程师、前端开发者
16
+
17
+ ## 功能亮点
18
+
19
+ - **🗺️ 底图管理 (MapBaseLayers)**
20
+ - 支持天地图矢量、影像、地形底图切换
21
+ - 动态切换底图与注记图层管理
22
+ - 地图裁剪与自定义范围显示
23
+ - 支持 GeoServer WMS 图层
24
+
25
+ - **📍 要素操作**
26
+ - **点位管理 (Point)**:点位标注(自定义图标、聚合、闪烁)
27
+ - **线要素绘制 (Line)**:线要素绘制(虚线、样式自定义)
28
+ - **面要素 (Polygon)**:面要素绘制、分区高亮、遮罩层
29
+ - **Vue组件支持 (VueTemplatePoint)**:支持将 Vue 组件作为地图点位渲染
30
+ - **河流图层 (RiverLayerManager)**:支持分级显示的河流图层管理
31
+
32
+ - **🛠️ 地图工具**
33
+ - **测量工具 (MeasureHandler)**:距离和面积测量
34
+ - **要素选择 (SelectHandler)**:支持点击、悬停、多选等交互选择
35
+ - **地图工具 (MapTools)**:图层管理、定位、视图自适应
36
+ - **事件管理 (EventManager)**:统一的地图事件监听与管理
37
+
38
+ - **⚡ 高级特性**
39
+ - **TypeScript 完全支持**:提供完整的类型定义
40
+ - **错误处理 (ErrorHandler)**:统一的错误捕获与日志
41
+ - **配置管理 (ConfigManager)**:集中管理默认配置
42
+ - **坐标系支持**:内置 CGCS2000 坐标系支持
43
+
44
+ ## 安装
45
+
46
+ ```bash
47
+ npm install my-openlayer
48
+ #
49
+ yarn add my-openlayer
50
+ #
51
+ pnpm add my-openlayer
52
+ ```
53
+
54
+ ### 依赖要求
55
+
56
+ - **Node.js**: >= 18
57
+ - **OpenLayers**: ^10.6.1
58
+ - **proj4**: ^2.7.5
59
+ - **@turf/turf**: ^7.2.0
60
+
61
+ ## 快速上手
62
+
63
+ ### 1. 初始化地图
64
+
65
+ ```typescript
66
+ import MyOl, { MapInitType } from 'my-openlayer';
67
+
68
+ const mapConfig: MapInitType = {
69
+ center: [119.81, 29.969],
70
+ zoom: 10,
71
+ token: import.meta.env.VITE_TIANDITU_TOKEN, // 天地图 Token
72
+ annotation: true
73
+ };
74
+
75
+ const map = new MyOl('map-container', mapConfig);
76
+ ```
77
+
78
+ ### 2. 使用功能模块
79
+
80
+ ```typescript
81
+ // 获取模块实例
82
+ const point = map.getPoint();
83
+ const line = map.getLine();
84
+ const polygon = map.getPolygon();
85
+
86
+ // 添加点位
87
+ point.addPoint([{ lgtd: 119.81, lttd: 29.969, name: '示例点' }], {
88
+ layerName: 'example-point',
89
+ img: 'marker.png'
90
+ });
91
+ ```
92
+
93
+ ## 文档索引
94
+
95
+ 为了提供更详细的说明,我们将文档拆分为独立的模块文件:
96
+
97
+ ### 核心类库
98
+ - **[MyOl](docs/MyOl.md)**: 地图入口类,负责初始化和模块访问。
99
+ - **[MapBaseLayers](docs/MapBaseLayers.md)**: 底图与注记管理。
100
+ - **[ConfigManager](docs/ConfigManager.md)**: 配置管理。
101
+ - **[EventManager](docs/EventManager.md)**: 事件管理。
102
+ - **[ErrorHandler](docs/ErrorHandler.md)**: 错误处理。
103
+
104
+ ### 要素操作
105
+ - **[Point](docs/Point.md)**: 点要素(含聚合、DOM点位)。
106
+ - **[Line](docs/Line.md)**: 线要素。
107
+ - **[Polygon](docs/Polygon.md)**: 面要素(含热力图、图片层)。
108
+ - **[VueTemplatePoint](docs/VueTemplatePoint.md)**: Vue 组件点位。
109
+ - **[RiverLayerManager](docs/RiverLayerManager.md)**: 河流图层管理。
110
+
111
+ ### 交互与工具
112
+ - **[SelectHandler](docs/SelectHandler.md)**: 要素选择交互(支持独立样式渲染、多选隔离)。
113
+ - **[MeasureHandler](docs/MeasureHandler.md)**: 测量工具。
114
+ - **[MapTools](docs/MapTools.md)**: 通用地图工具。
115
+ - **[ValidationUtils](docs/ValidationUtils.md)**: 验证工具。
116
+
117
+ ## 详细用法示例
118
+
119
+ ### 底图切换
120
+
121
+ ```typescript
122
+ const baseLayers = map.getMapBaseLayers();
123
+ baseLayers.switchBaseLayer('img_c'); // 切换到影像底图
124
+ ```
125
+
126
+ ### 测量工具
127
+
128
+ ```typescript
129
+ import { MeasureHandler } from 'my-openlayer';
130
+
131
+ // 需要传入原生的 OpenLayers map 实例
132
+ const measure = new MeasureHandler(map.map);
133
+
134
+ measure.start('LineString'); // 开始测距
135
+ measure.end(); // 结束测量
136
+ ```
137
+
138
+ > 注意:部分高级功能(如 SelectHandler)可以通过 `map.getSelectHandler()` 访问。
139
+
140
+ ## 贡献指南
141
+
142
+ 欢迎提交 Issue 或 Pull Request!
143
+
144
+ 1. Fork 本仓库
145
+ 2. 新建分支:`git checkout -b feature/your-feature`
146
+ 3. 提交更改:`git commit -m 'feat: 新功能描述'`
147
+ 4. 推送分支:`git push origin feature/your-feature`
148
+ 5. 提交 Pull Request
149
+
150
+ ## 许可证
151
+
152
+ [MIT](LICENSE)
153
+
154
+ ---
155
+
156
+ **联系方式**: 2364184627@qq.com | [GitHub Issues](https://github.com/cuteyuchen/my-openlayer/issues)