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