my-openlayer 3.0.1 → 3.1.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/CHANGELOG.md +21 -0
- package/MyOl.d.ts +13 -0
- package/MyOl.js +72 -30
- package/README.md +43 -4
- package/core/geojson/GeoJSONRenderer.d.ts +30 -0
- package/core/geojson/GeoJSONRenderer.js +251 -0
- package/core/geojson/index.d.ts +2 -0
- package/core/geojson/index.js +1 -0
- package/core/line/Line.js +4 -4
- package/core/line/index.d.ts +0 -2
- package/core/line/index.js +0 -1
- package/core/map/ConfigManager.d.ts +0 -42
- package/core/map/ConfigManager.js +1 -13
- package/core/map/MapBaseLayers.js +11 -11
- package/core/map/MapTools.js +15 -15
- package/core/map/MeasureHandler.js +2 -2
- package/core/point/Point.d.ts +17 -14
- package/core/point/Point.js +38 -34
- package/core/polygon/Polygon.js +4 -4
- package/core/select/SelectHandler.js +7 -11
- package/core/vue-template-point/VueTemplatePoint.js +13 -13
- package/docs/.vitepress/config.mts +1 -2
- package/docs/MIGRATION-3.0.md +24 -0
- package/docs/Point.md +64 -9
- package/index.d.ts +4 -3
- package/index.js +3 -1
- package/package.json +1 -1
- package/types/geojson.d.ts +113 -0
- package/types/geojson.js +4 -0
- package/types/index.d.ts +2 -1
- package/types/point.d.ts +13 -0
- package/utils/GeoJSONProcessor.d.ts +77 -0
- package/utils/GeoJSONProcessor.js +299 -0
- package/utils/ValidationUtils.d.ts +0 -4
- package/utils/ValidationUtils.js +16 -15
- package/core/line/RiverLayerManager.d.ts +0 -93
- package/core/line/RiverLayerManager.js +0 -340
- package/docs/RiverLayerManager.md +0 -187
|
@@ -7,7 +7,7 @@ import Collection from 'ol/Collection';
|
|
|
7
7
|
import { getUid } from "ol/util";
|
|
8
8
|
import EventManager from "../map/EventManager";
|
|
9
9
|
import ValidationUtils from "../../utils/ValidationUtils";
|
|
10
|
-
import { ErrorHandler,
|
|
10
|
+
import { ErrorHandler, ErrorType } from "../../utils/ErrorHandler";
|
|
11
11
|
/**
|
|
12
12
|
* 要素选择处理器类
|
|
13
13
|
* 用于在地图上选择和高亮显示要素,支持单选、多选等多种选择模式
|
|
@@ -88,8 +88,7 @@ export default class SelectHandler {
|
|
|
88
88
|
return this;
|
|
89
89
|
}
|
|
90
90
|
catch (error) {
|
|
91
|
-
this.errorHandler.
|
|
92
|
-
throw error;
|
|
91
|
+
throw this.errorHandler.createAndHandleError(`启用要素选择失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.COMPONENT_ERROR, { mode, options });
|
|
93
92
|
}
|
|
94
93
|
}
|
|
95
94
|
/**
|
|
@@ -111,8 +110,7 @@ export default class SelectHandler {
|
|
|
111
110
|
return this;
|
|
112
111
|
}
|
|
113
112
|
catch (error) {
|
|
114
|
-
this.errorHandler.
|
|
115
|
-
throw error;
|
|
113
|
+
throw this.errorHandler.createAndHandleError(`禁用要素选择失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.COMPONENT_ERROR);
|
|
116
114
|
}
|
|
117
115
|
}
|
|
118
116
|
/**
|
|
@@ -160,8 +158,7 @@ export default class SelectHandler {
|
|
|
160
158
|
return this;
|
|
161
159
|
}
|
|
162
160
|
catch (error) {
|
|
163
|
-
this.errorHandler.
|
|
164
|
-
throw error;
|
|
161
|
+
throw this.errorHandler.createAndHandleError(`通过ID选择要素失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.COMPONENT_ERROR, { featureIds, options });
|
|
165
162
|
}
|
|
166
163
|
}
|
|
167
164
|
/**
|
|
@@ -170,7 +167,7 @@ export default class SelectHandler {
|
|
|
170
167
|
selectByProperty(propertyName, propertyValue, options) {
|
|
171
168
|
try {
|
|
172
169
|
if (!propertyName)
|
|
173
|
-
throw
|
|
170
|
+
throw ErrorHandler.getInstance().createAndHandleError('属性名称不能为空', ErrorType.VALIDATION_ERROR);
|
|
174
171
|
const selectedFeatures = this.findFeaturesByProperty(propertyName, propertyValue, options?.layerName);
|
|
175
172
|
if (selectedFeatures.length === 0)
|
|
176
173
|
return this;
|
|
@@ -178,8 +175,7 @@ export default class SelectHandler {
|
|
|
178
175
|
return this;
|
|
179
176
|
}
|
|
180
177
|
catch (error) {
|
|
181
|
-
this.errorHandler.
|
|
182
|
-
throw error;
|
|
178
|
+
throw this.errorHandler.createAndHandleError(`通过属性选择要素失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.COMPONENT_ERROR, { propertyName, propertyValue, options });
|
|
183
179
|
}
|
|
184
180
|
}
|
|
185
181
|
/**
|
|
@@ -344,7 +340,7 @@ export default class SelectHandler {
|
|
|
344
340
|
this.errorHandler.debug('选择处理器已销毁');
|
|
345
341
|
}
|
|
346
342
|
catch (error) {
|
|
347
|
-
this.errorHandler.
|
|
343
|
+
this.errorHandler.createAndHandleError(`销毁选择处理器失败: ${error instanceof Error ? error.message : '未知错误'}`, ErrorType.COMPONENT_ERROR);
|
|
348
344
|
}
|
|
349
345
|
}
|
|
350
346
|
getSelectCondition(mode) {
|
|
@@ -84,16 +84,16 @@ export default class VueTemplatePoint {
|
|
|
84
84
|
*/
|
|
85
85
|
addVueTemplatePoint(pointDataList, template, options) {
|
|
86
86
|
if (!pointDataList || !Array.isArray(pointDataList) || pointDataList.length === 0) {
|
|
87
|
-
throw
|
|
87
|
+
throw ErrorHandler.getInstance().createAndHandleError('Valid point info list is required', ErrorType.VALIDATION_ERROR);
|
|
88
88
|
}
|
|
89
89
|
if (!template) {
|
|
90
|
-
throw
|
|
90
|
+
throw ErrorHandler.getInstance().createAndHandleError('Vue template is required', ErrorType.VALIDATION_ERROR);
|
|
91
91
|
}
|
|
92
92
|
try {
|
|
93
93
|
const instances = [];
|
|
94
94
|
pointDataList.forEach((pointData) => {
|
|
95
95
|
if (!ValidationUtils.validateLngLat(pointData.lgtd, pointData.lttd)) {
|
|
96
|
-
throw
|
|
96
|
+
throw ErrorHandler.getInstance().createAndHandleError('Valid longitude and latitude are required for each point', ErrorType.VALIDATION_ERROR);
|
|
97
97
|
}
|
|
98
98
|
const pointOptions = {
|
|
99
99
|
Template: template,
|
|
@@ -137,7 +137,7 @@ export default class VueTemplatePoint {
|
|
|
137
137
|
};
|
|
138
138
|
}
|
|
139
139
|
catch (error) {
|
|
140
|
-
throw
|
|
140
|
+
throw ErrorHandler.getInstance().createAndHandleError(`Failed to create Vue template points: ${error}`, ErrorType.COMPONENT_ERROR);
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
@@ -217,7 +217,7 @@ class VueTemplatePointInstanceImpl {
|
|
|
217
217
|
const { Template, lgtd, lttd } = options;
|
|
218
218
|
ValidationUtils.validateRequired(Template, 'Template is required in options');
|
|
219
219
|
if (typeof lgtd !== 'number' || typeof lttd !== 'number') {
|
|
220
|
-
throw
|
|
220
|
+
throw ErrorHandler.getInstance().createAndHandleError('Longitude and lttd must be numbers', ErrorType.VALIDATION_ERROR);
|
|
221
221
|
}
|
|
222
222
|
ValidationUtils.validateCoordinate(lgtd, lttd);
|
|
223
223
|
}
|
|
@@ -264,7 +264,7 @@ class VueTemplatePointInstanceImpl {
|
|
|
264
264
|
createVueApp() {
|
|
265
265
|
const { Template, props } = this.options;
|
|
266
266
|
if (!Vue) {
|
|
267
|
-
throw
|
|
267
|
+
throw ErrorHandler.getInstance().createAndHandleError('Vue is not available. Please ensure Vue is installed in your project.', ErrorType.COMPONENT_ERROR);
|
|
268
268
|
}
|
|
269
269
|
// 清空DOM内容,确保没有残留
|
|
270
270
|
this.dom.innerHTML = '';
|
|
@@ -289,7 +289,7 @@ class VueTemplatePointInstanceImpl {
|
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
291
|
catch (error) {
|
|
292
|
-
throw
|
|
292
|
+
throw ErrorHandler.getInstance().createAndHandleError(`Failed to create Vue app: ${error}`, ErrorType.COMPONENT_ERROR);
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
/**
|
|
@@ -323,7 +323,7 @@ class VueTemplatePointInstanceImpl {
|
|
|
323
323
|
*/
|
|
324
324
|
setVisible(visible) {
|
|
325
325
|
if (this.state === VueTemplatePointState.DESTROYED) {
|
|
326
|
-
throw
|
|
326
|
+
throw ErrorHandler.getInstance().createAndHandleError('Cannot set visibility on destroyed DOM point', ErrorType.COMPONENT_ERROR);
|
|
327
327
|
}
|
|
328
328
|
ValidationUtils.validateType(visible, 'boolean', 'Visible parameter must be a boolean');
|
|
329
329
|
try {
|
|
@@ -350,7 +350,7 @@ class VueTemplatePointInstanceImpl {
|
|
|
350
350
|
*/
|
|
351
351
|
updatePosition(lgtd, lttd) {
|
|
352
352
|
if (this.state === VueTemplatePointState.DESTROYED) {
|
|
353
|
-
throw
|
|
353
|
+
throw ErrorHandler.getInstance().createAndHandleError('Cannot update position on destroyed DOM point', ErrorType.COMPONENT_ERROR);
|
|
354
354
|
}
|
|
355
355
|
ValidationUtils.validateCoordinate(lgtd, lttd);
|
|
356
356
|
try {
|
|
@@ -376,7 +376,7 @@ class VueTemplatePointInstanceImpl {
|
|
|
376
376
|
*/
|
|
377
377
|
updateProps(newProps) {
|
|
378
378
|
if (this.state === VueTemplatePointState.DESTROYED) {
|
|
379
|
-
throw
|
|
379
|
+
throw ErrorHandler.getInstance().createAndHandleError('Cannot update props on destroyed DOM point', ErrorType.COMPONENT_ERROR);
|
|
380
380
|
}
|
|
381
381
|
try {
|
|
382
382
|
// 重新创建Vue应用实例。
|
|
@@ -409,7 +409,7 @@ class VueTemplatePointInstanceImpl {
|
|
|
409
409
|
*/
|
|
410
410
|
setStyle(styles) {
|
|
411
411
|
if (this.state === VueTemplatePointState.DESTROYED) {
|
|
412
|
-
throw
|
|
412
|
+
throw ErrorHandler.getInstance().createAndHandleError('Cannot set style on destroyed DOM point', ErrorType.COMPONENT_ERROR);
|
|
413
413
|
}
|
|
414
414
|
try {
|
|
415
415
|
Object.assign(this.dom.style, styles);
|
|
@@ -426,7 +426,7 @@ class VueTemplatePointInstanceImpl {
|
|
|
426
426
|
*/
|
|
427
427
|
addClass(className) {
|
|
428
428
|
if (this.state === VueTemplatePointState.DESTROYED) {
|
|
429
|
-
throw
|
|
429
|
+
throw ErrorHandler.getInstance().createAndHandleError('Cannot add class to destroyed DOM point', ErrorType.COMPONENT_ERROR);
|
|
430
430
|
}
|
|
431
431
|
ValidationUtils.validateNonEmptyString(className, 'Valid class name is required');
|
|
432
432
|
try {
|
|
@@ -444,7 +444,7 @@ class VueTemplatePointInstanceImpl {
|
|
|
444
444
|
*/
|
|
445
445
|
removeClass(className) {
|
|
446
446
|
if (this.state === VueTemplatePointState.DESTROYED) {
|
|
447
|
-
throw
|
|
447
|
+
throw ErrorHandler.getInstance().createAndHandleError('Cannot remove class from destroyed DOM point', ErrorType.COMPONENT_ERROR);
|
|
448
448
|
}
|
|
449
449
|
ValidationUtils.validateNonEmptyString(className, 'Valid class name is required');
|
|
450
450
|
try {
|
|
@@ -31,8 +31,7 @@ export default defineConfig({
|
|
|
31
31
|
{ text: 'Point 点要素', link: '/Point' },
|
|
32
32
|
{ text: 'Line 线要素', link: '/Line' },
|
|
33
33
|
{ text: 'Polygon 面要素', link: '/Polygon' },
|
|
34
|
-
{ text: 'VueTemplatePoint Vue点位', link: '/VueTemplatePoint' }
|
|
35
|
-
{ text: 'RiverLayerManager 河流图层', link: '/RiverLayerManager' }
|
|
34
|
+
{ text: 'VueTemplatePoint Vue点位', link: '/VueTemplatePoint' }
|
|
36
35
|
]
|
|
37
36
|
},
|
|
38
37
|
{
|
package/docs/MIGRATION-3.0.md
CHANGED
|
@@ -117,6 +117,30 @@ const handle = await myOl.getPoint().addPulsePointLayerByUrl('/villages.json', {
|
|
|
117
117
|
})
|
|
118
118
|
```
|
|
119
119
|
|
|
120
|
+
### 2.3.1 点 API 支持 GeoJSON 直接输入
|
|
121
|
+
|
|
122
|
+
3.0 点 API(`addPoint` / `addClusterPoint` / `addPulsePointLayer`)现在直接接受标准 GeoJSON 点数据,无需手动将 `FeatureCollection` 转为 `PointData[]`:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
// ❌ 3.0 之前:需要手动转换
|
|
126
|
+
const fc = await fetch('/stations.geojson').then(r => r.json())
|
|
127
|
+
const pointData = fc.features.map(f => ({
|
|
128
|
+
...f.properties,
|
|
129
|
+
lgtd: f.geometry.coordinates[0],
|
|
130
|
+
lttd: f.geometry.coordinates[1]
|
|
131
|
+
}))
|
|
132
|
+
point.addPoint(pointData, { layerName: 'stations' })
|
|
133
|
+
|
|
134
|
+
// ✅ 3.0:直接传 GeoJSON
|
|
135
|
+
const fc = await fetch('/stations.geojson').then(r => r.json())
|
|
136
|
+
point.addPoint(fc, { layerName: 'stations' })
|
|
137
|
+
|
|
138
|
+
// 也支持单个 Feature、MultiPoint geometry 等形态
|
|
139
|
+
point.addPoint({ type: 'Feature', properties: { name: 'A' }, geometry: { type: 'Point', coordinates: [120, 30] } }, { layerName: 'single' })
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`*ByUrl` 方法内部已统一使用同一套标准化逻辑,不再各自手写 JSON 映射。
|
|
143
|
+
|
|
120
144
|
### 2.4 投影注册抽到 `ProjectionManager`
|
|
121
145
|
|
|
122
146
|
2.x 用 `options.projection` 注册自定义投影。3.0 仍然支持,**外加**一个独立入口:
|
package/docs/Point.md
CHANGED
|
@@ -22,6 +22,8 @@ constructor(map: Map)
|
|
|
22
22
|
| img | `string` | 图标图片的 URL |
|
|
23
23
|
| scale | `number` | 图标缩放比例 |
|
|
24
24
|
| iconColor | `string` | 图标颜色(用于改变图标色调) |
|
|
25
|
+
| circleColor | `string` | 圆点填充颜色。未设置 img 时生效,与 circleRadius 搭配绘制纯色圆点 |
|
|
26
|
+
| circleRadius | `number` | 圆点半径(像素),默认 6。仅在未设置 img 时生效 |
|
|
25
27
|
| layerName | `string` | 图层名称(必填,继承自 BaseOptions) |
|
|
26
28
|
| zIndex | `number` | 图层层级 |
|
|
27
29
|
| visible | `boolean` | 是否可见 |
|
|
@@ -72,6 +74,28 @@ constructor(map: Map)
|
|
|
72
74
|
| lttd | `number` | 纬度 |
|
|
73
75
|
| [key: string] | `any` | 其他业务数据字段 |
|
|
74
76
|
|
|
77
|
+
### PointJSONInput
|
|
78
|
+
|
|
79
|
+
点 API 统一输入类型。`addPoint` / `addClusterPoint` / `addPulsePointLayer` 均接受以下任意形态:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
type PointJSONInput =
|
|
83
|
+
| PointData[] // 传统数组
|
|
84
|
+
| MapJSONData // GeoJSON FeatureCollection
|
|
85
|
+
| FeatureData // 单个 GeoJSON Feature
|
|
86
|
+
| { type: 'Point'; coordinates: number[] } // 裸 Point geometry
|
|
87
|
+
| { type: 'MultiPoint'; coordinates: number[][] } // 裸 MultiPoint geometry
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
标准化规则:
|
|
91
|
+
- `FeatureCollection` 中只提取 `Point` / `MultiPoint` 类型的 Feature,其他 geometry 类型被跳过。
|
|
92
|
+
- `MultiPoint` 会被拆分为多个独立的 `PointData`。
|
|
93
|
+
- GeoJSON Feature 的 `properties` 会被保留,与 `lgtd` / `lttd` 合并。
|
|
94
|
+
- 坐标含 `NaN`、`Infinity` 或缺失的点会被过滤。
|
|
95
|
+
- 不支持 `lng/lat`、`longitude/latitude`、`x/y` 等字段别名。
|
|
96
|
+
|
|
97
|
+
> 本优化借鉴 [mapshaper](https://github.com/mbloch/mapshaper) 对地理数据输入的统一处理思路,但仅提供轻量点数据标准化能力,不包含拓扑简化、dissolve、clip/erase 等 GIS 编辑功能。
|
|
98
|
+
|
|
75
99
|
### VueTemplatePointOptions
|
|
76
100
|
|
|
77
101
|
| 属性名 | 类型 | 说明 |
|
|
@@ -91,25 +115,25 @@ constructor(map: Map)
|
|
|
91
115
|
|
|
92
116
|
### addPoint
|
|
93
117
|
|
|
94
|
-
|
|
118
|
+
添加普通点图层。支持 `PointJSONInput` 任意形态(`PointData[]`、GeoJSON FeatureCollection、Feature、裸 geometry)。
|
|
95
119
|
|
|
96
120
|
```typescript
|
|
97
|
-
addPoint(pointData:
|
|
121
|
+
addPoint(pointData: PointJSONInput, options: PointOptions & { layerName: string }): LayerHandle<VectorLayer<VectorSource>> | null
|
|
98
122
|
```
|
|
99
123
|
|
|
100
|
-
- **pointData**:
|
|
124
|
+
- **pointData**: 点位数据,支持 `PointData[]` 或标准 GeoJSON 点数据。
|
|
101
125
|
- **options**: 配置选项。
|
|
102
126
|
- **返回值**: `{ layer, remove(), setVisible() }` 形态的统一句柄;如果数据无效返回 `null`。
|
|
103
127
|
|
|
104
128
|
### addClusterPoint
|
|
105
129
|
|
|
106
|
-
|
|
130
|
+
添加聚合点图层。支持 `PointJSONInput` 任意形态。
|
|
107
131
|
|
|
108
132
|
```typescript
|
|
109
|
-
addClusterPoint(pointData:
|
|
133
|
+
addClusterPoint(pointData: PointJSONInput, options: ClusterOptions & { layerName: string }): LayerHandle<VectorLayer<VectorSource>> | null
|
|
110
134
|
```
|
|
111
135
|
|
|
112
|
-
- **pointData**:
|
|
136
|
+
- **pointData**: 点位数据,支持 `PointData[]` 或标准 GeoJSON 点数据。
|
|
113
137
|
- **options**: 聚合配置选项。
|
|
114
138
|
- **返回值**: `{ layer, remove(), setVisible() }` 形态的统一句柄。
|
|
115
139
|
|
|
@@ -140,13 +164,13 @@ addDomPoint(twinkleList: TwinkleItem[], callback?: Function): {
|
|
|
140
164
|
|
|
141
165
|
### addPulsePointLayer
|
|
142
166
|
|
|
143
|
-
|
|
167
|
+
添加高性能闪烁点图层。支持 `PointJSONInput` 任意形态。
|
|
144
168
|
|
|
145
169
|
```typescript
|
|
146
|
-
addPulsePointLayer(pointData:
|
|
170
|
+
addPulsePointLayer(pointData: PointJSONInput, options: PulsePointOptions & { layerName: string }): PulsePointLayerHandle | null
|
|
147
171
|
```
|
|
148
172
|
|
|
149
|
-
- **pointData**:
|
|
173
|
+
- **pointData**: 点位数据,支持 `PointData[]` 或标准 GeoJSON 点数据。
|
|
150
174
|
- **options**: 闪烁点配置选项,复用 `addPoint` 的图标、文本和图层参数习惯。
|
|
151
175
|
- **返回值**: 控制对象,包含动画启停、显隐、数据更新和移除方法;如果数据无效返回 `null`。
|
|
152
176
|
|
|
@@ -249,3 +273,34 @@ const ctrl = point.addVueTemplatePoint(data, MyComponent, {
|
|
|
249
273
|
// 隐藏所有点
|
|
250
274
|
ctrl.setVisible(false);
|
|
251
275
|
```
|
|
276
|
+
|
|
277
|
+
### 使用 GeoJSON 数据添加点位
|
|
278
|
+
|
|
279
|
+
从 3.0 起,点 API 直接接受标准 GeoJSON 点数据,无需手动转换:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
// 方式一:GeoJSON FeatureCollection
|
|
283
|
+
const fc = {
|
|
284
|
+
type: 'FeatureCollection',
|
|
285
|
+
features: [
|
|
286
|
+
{ type: 'Feature', properties: { name: '北京' }, geometry: { type: 'Point', coordinates: [116.40, 39.90] } },
|
|
287
|
+
{ type: 'Feature', properties: { name: '上海' }, geometry: { type: 'Point', coordinates: [121.47, 31.23] } }
|
|
288
|
+
]
|
|
289
|
+
};
|
|
290
|
+
const handle = point.addPoint(fc, { layerName: 'cities', textKey: 'name' });
|
|
291
|
+
|
|
292
|
+
// 方式二:单个 Feature
|
|
293
|
+
const feature = { type: 'Feature', properties: { name: '杭州' }, geometry: { type: 'Point', coordinates: [120.15, 30.27] } };
|
|
294
|
+
point.addPoint(feature, { layerName: 'single-city' });
|
|
295
|
+
|
|
296
|
+
// 方式三:MultiPoint Feature(自动拆分为多个点)
|
|
297
|
+
const multiPoint = { type: 'Feature', properties: { region: '华东' }, geometry: { type: 'MultiPoint', coordinates: [[120, 30], [121, 31]] } };
|
|
298
|
+
point.addPoint(multiPoint, { layerName: 'region' });
|
|
299
|
+
|
|
300
|
+
// 闪烁点同样支持 GeoJSON 输入
|
|
301
|
+
const pulseHandle = point.addPulsePointLayer(fc, {
|
|
302
|
+
layerName: 'villages',
|
|
303
|
+
levelKey: 'lev',
|
|
304
|
+
pulse: { enabled: true, radius: [8, 28] }
|
|
305
|
+
});
|
|
306
|
+
```
|
package/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export { default } from './MyOl';
|
|
2
2
|
export { default as MyOl } from './MyOl';
|
|
3
3
|
export { Point } from './core/point';
|
|
4
|
-
export { Line
|
|
5
|
-
export type { RiverLayerOptions, RiverLevelWidthMap } from './core/line';
|
|
4
|
+
export { Line } from './core/line';
|
|
6
5
|
export { Polygon } from './core/polygon';
|
|
7
6
|
export { MapBaseLayers, MapTools, MeasureHandler, ConfigManager, EventManager } from './core/map';
|
|
8
7
|
export { VueTemplatePoint } from './core/vue-template-point';
|
|
@@ -12,8 +11,10 @@ export type { CustomProjectionRegistration } from './core/projection';
|
|
|
12
11
|
export type { MapEventType, EventCallback, MapEventData } from './core/map/EventManager';
|
|
13
12
|
export { ErrorHandler, MyOpenLayersError, ErrorType, LayerNotFoundError, InvalidGeoJSONError, ProjectionError } from './utils/ErrorHandler';
|
|
14
13
|
export { default as ValidationUtils } from './utils/ValidationUtils';
|
|
14
|
+
export { normalizePointData } from './utils/GeoJSONProcessor';
|
|
15
|
+
export type { PointJSONInput } from './types';
|
|
15
16
|
export type { BaseOptions, StyleOptions, TextOptions, LayerHandle, AnimatedLayerHandle } from './types';
|
|
16
17
|
export type { PointOptions, LineOptions, FlowLineOptions, FlowLineLayerHandle, PolygonOptions, PulsePointOptions, PulsePointLayerHandle } from './types';
|
|
17
18
|
export type { OptionsType } from './types';
|
|
18
|
-
export type { MapInitType, MapLayersOptions, HeatMapOptions, ImageLayerData, MaskLayerOptions, FeatureColorUpdateOptions, PointData, PulsePointIconOptions, LineData, ClusterOptions, MeasureHandlerType, VueTemplatePointOptions, VueTemplatePointInstance, TwinkleItem, MapJSONData, FeatureData, AnnotationType, TiandituType, MapLayers, AnnotationLayerOptions, SelectOptions, SelectMode, SelectCallbackEvent, ProgrammaticSelectOptions } from './types';
|
|
19
|
+
export type { MapInitType, MapLayersOptions, HeatMapOptions, ImageLayerData, MaskLayerOptions, FeatureColorUpdateOptions, PointData, PulsePointIconOptions, LineData, ClusterOptions, MeasureHandlerType, VueTemplatePointOptions, VueTemplatePointInstance, TwinkleItem, MapJSONData, FeatureData, AddGeoJSONInput, GeoJSONGeometryType, GeoJSONGroupBy, GeoJSONLayerName, AddGeoJSONPointOptions, AddGeoJSONOptions, GeoJSONGroupHandle, GeoJSONRenderHandle, AnnotationType, TiandituType, MapLayers, AnnotationLayerOptions, SelectOptions, SelectMode, SelectCallbackEvent, ProgrammaticSelectOptions } from './types';
|
|
19
20
|
export { VueTemplatePointState } from './types';
|
package/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export { default } from './MyOl';
|
|
3
3
|
export { default as MyOl } from './MyOl';
|
|
4
4
|
export { Point } from './core/point';
|
|
5
|
-
export { Line
|
|
5
|
+
export { Line } from './core/line';
|
|
6
6
|
export { Polygon } from './core/polygon';
|
|
7
7
|
export { MapBaseLayers, MapTools, MeasureHandler, ConfigManager, EventManager } from './core/map';
|
|
8
8
|
export { VueTemplatePoint } from './core/vue-template-point';
|
|
@@ -12,5 +12,7 @@ export { ProjectionManager, PROJECTIONS } from './core/projection';
|
|
|
12
12
|
export { ErrorHandler, MyOpenLayersError, ErrorType, LayerNotFoundError, InvalidGeoJSONError, ProjectionError } from './utils/ErrorHandler';
|
|
13
13
|
// 验证工具
|
|
14
14
|
export { default as ValidationUtils } from './utils/ValidationUtils';
|
|
15
|
+
// GeoJSON 数据标准化
|
|
16
|
+
export { normalizePointData } from './utils/GeoJSONProcessor';
|
|
15
17
|
// Vue 模板点位状态枚举(运行时值,需要单独导出)
|
|
16
18
|
export { VueTemplatePointState } from './types';
|
package/package.json
CHANGED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* addGeoJSON 综合方法相关类型定义。
|
|
3
|
+
*/
|
|
4
|
+
import type { FeatureData, MapJSONData } from './common';
|
|
5
|
+
import type { PointOptions } from './point';
|
|
6
|
+
import type { LineOptions } from './line';
|
|
7
|
+
import type { PolygonOptions } from './polygon';
|
|
8
|
+
import type { LayerHandle } from './handle';
|
|
9
|
+
/** *********************输入类型*********************/
|
|
10
|
+
/**
|
|
11
|
+
* 裸 GeoJSON geometry 对象(非 Feature、非 FeatureCollection)。
|
|
12
|
+
*/
|
|
13
|
+
type GeometryLike = {
|
|
14
|
+
type: string;
|
|
15
|
+
coordinates: unknown;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* addGeoJSON 统一输入类型。
|
|
19
|
+
* 支持单个 GeoJSON、数组、或 `{ key: json }` 对象。
|
|
20
|
+
*/
|
|
21
|
+
export type AddGeoJSONInput = MapJSONData | FeatureData | GeometryLike | Array<MapJSONData | FeatureData | GeometryLike> | Record<string, MapJSONData | FeatureData | GeometryLike>;
|
|
22
|
+
/** *********************分组与命名类型*********************/
|
|
23
|
+
/**
|
|
24
|
+
* GeoJSON 几何分类(简化为三大类)。
|
|
25
|
+
*/
|
|
26
|
+
export type GeoJSONGeometryType = 'point' | 'line' | 'polygon';
|
|
27
|
+
/**
|
|
28
|
+
* 分组依据:属性名字符串或回调函数。
|
|
29
|
+
*/
|
|
30
|
+
export type GeoJSONGroupBy = string | ((properties: Record<string, unknown>, context: {
|
|
31
|
+
datasetKey: string;
|
|
32
|
+
geometryType: GeoJSONGeometryType;
|
|
33
|
+
feature: FeatureData;
|
|
34
|
+
index: number;
|
|
35
|
+
}) => string | number | undefined | null);
|
|
36
|
+
/**
|
|
37
|
+
* 图层命名:字符串、字符串数组、对象映射、或回调函数。
|
|
38
|
+
*/
|
|
39
|
+
export type GeoJSONLayerName = string | string[] | Record<string, string> | ((context: {
|
|
40
|
+
datasetKey: string;
|
|
41
|
+
groupKey: string;
|
|
42
|
+
geometryType: GeoJSONGeometryType;
|
|
43
|
+
index: number;
|
|
44
|
+
}) => string);
|
|
45
|
+
/** *********************选项类型*********************/
|
|
46
|
+
/**
|
|
47
|
+
* addGeoJSON 点图层专用选项,扩展了 styleByProperties 回调。
|
|
48
|
+
*/
|
|
49
|
+
export interface AddGeoJSONPointOptions extends PointOptions {
|
|
50
|
+
/**
|
|
51
|
+
* 按 feature properties 返回不同样式选项。
|
|
52
|
+
* properties 为原始 GeoJSON Feature.properties,不包含点坐标转换产生的 lgtd/lttd。
|
|
53
|
+
* context.feature 为真实 GeoJSON Feature,context.index 为当前点分组内索引。
|
|
54
|
+
* 回调结果与 base options 合并,回调结果优先(style 字段除外)。
|
|
55
|
+
*/
|
|
56
|
+
styleByProperties?: (properties: Record<string, unknown>, context: {
|
|
57
|
+
datasetKey: string;
|
|
58
|
+
groupKey: string;
|
|
59
|
+
feature: FeatureData;
|
|
60
|
+
index: number;
|
|
61
|
+
}) => Partial<PointOptions> | undefined | null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* addGeoJSON 方法配置选项。
|
|
65
|
+
*/
|
|
66
|
+
export interface AddGeoJSONOptions {
|
|
67
|
+
/** 图层命名规则。 */
|
|
68
|
+
layerName: GeoJSONLayerName;
|
|
69
|
+
/** 分组依据:属性名或回调函数。 */
|
|
70
|
+
groupBy?: GeoJSONGroupBy;
|
|
71
|
+
/** 数据坐标系。 */
|
|
72
|
+
dataProjection?: string;
|
|
73
|
+
/** 地图坐标系。 */
|
|
74
|
+
featureProjection?: string;
|
|
75
|
+
/** 是否自动缩放到数据范围。 */
|
|
76
|
+
fitView?: boolean;
|
|
77
|
+
/** 点图层选项。 */
|
|
78
|
+
point?: AddGeoJSONPointOptions;
|
|
79
|
+
/** 线图层选项。 */
|
|
80
|
+
line?: LineOptions;
|
|
81
|
+
/** 面图层选项。 */
|
|
82
|
+
polygon?: PolygonOptions;
|
|
83
|
+
}
|
|
84
|
+
/** *********************句柄类型*********************/
|
|
85
|
+
/**
|
|
86
|
+
* 单个分组的图层句柄集合。
|
|
87
|
+
*/
|
|
88
|
+
export interface GeoJSONGroupHandle {
|
|
89
|
+
point: LayerHandle | null;
|
|
90
|
+
line: LayerHandle | null;
|
|
91
|
+
polygon: LayerHandle | null;
|
|
92
|
+
handles: LayerHandle[];
|
|
93
|
+
setVisible(visible: boolean): void;
|
|
94
|
+
remove(): void;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* addGeoJSON 返回的总句柄,支持整体和按组控制。
|
|
98
|
+
*/
|
|
99
|
+
export interface GeoJSONRenderHandle {
|
|
100
|
+
groups: Record<string, GeoJSONGroupHandle>;
|
|
101
|
+
handles: LayerHandle[];
|
|
102
|
+
/** 按 groupKey 索引的点图层句柄,方便 handle.point[groupKey] 访问。 */
|
|
103
|
+
point: Record<string, LayerHandle | null>;
|
|
104
|
+
/** 按 groupKey 索引的线图层句柄,方便 handle.line[groupKey] 访问。 */
|
|
105
|
+
line: Record<string, LayerHandle | null>;
|
|
106
|
+
/** 按 groupKey 索引的面图层句柄,方便 handle.polygon[groupKey] 访问。 */
|
|
107
|
+
polygon: Record<string, LayerHandle | null>;
|
|
108
|
+
setVisible(visible: boolean): void;
|
|
109
|
+
setGroupVisible(groupKey: string, visible: boolean): void;
|
|
110
|
+
removeGroup(groupKey: string): void;
|
|
111
|
+
remove(): void;
|
|
112
|
+
}
|
|
113
|
+
export {};
|
package/types/geojson.js
ADDED
package/types/index.d.ts
CHANGED
|
@@ -2,9 +2,10 @@ export type { BaseOptions, StyleOptions, TextOptions } from './base';
|
|
|
2
2
|
export type { LayerHandle, AnimatedLayerHandle, ControlHandle } from './handle';
|
|
3
3
|
export type { FeatureData, MapJSONData, OptionsType, MeasureHandlerType, EventType } from './common';
|
|
4
4
|
export type { MapInitType, MapLayersOptions, MapLayers, AnnotationType, TiandituType, AnnotationLayerOptions, HeatMapOptions, ImageLayerData, MaskLayerOptions } from './map';
|
|
5
|
-
export type { PointOptions, PointData, ClusterOptions, PulsePointIconOptions, PulsePointOptions, PulsePointLayerHandle, TwinkleItem } from './point';
|
|
5
|
+
export type { PointOptions, PointData, PointJSONInput, ClusterOptions, PulsePointIconOptions, PulsePointOptions, PulsePointLayerHandle, TwinkleItem } from './point';
|
|
6
6
|
export type { LineOptions, LineData, FlowLineOptions, FlowLineLayerHandle } from './line';
|
|
7
7
|
export type { PolygonOptions, FeatureColorUpdateOptions } from './polygon';
|
|
8
|
+
export type { AddGeoJSONInput, GeoJSONGeometryType, GeoJSONGroupBy, GeoJSONLayerName, AddGeoJSONPointOptions, AddGeoJSONOptions, GeoJSONGroupHandle, GeoJSONRenderHandle } from './geojson';
|
|
8
9
|
export type { SelectOptions, SelectMode, SelectCallbackEvent, ProgrammaticSelectOptions } from './select';
|
|
9
10
|
export type { VueInstance, VueApp, VueLegacyInstance, VueTemplatePointOptions, VueTemplatePointInstance } from './vue-template-point';
|
|
10
11
|
export { VueTemplatePointState } from './vue-template-point';
|
package/types/point.d.ts
CHANGED
|
@@ -2,17 +2,30 @@ import VectorLayer from "ol/layer/Vector";
|
|
|
2
2
|
import VectorSource from "ol/source/Vector";
|
|
3
3
|
import type { BaseOptions, StyleOptions, TextOptions } from "./base";
|
|
4
4
|
import type { AnimatedLayerHandle } from "./handle";
|
|
5
|
+
import type { FeatureData, MapJSONData } from "./common";
|
|
5
6
|
export interface PointOptions extends BaseOptions, StyleOptions, TextOptions {
|
|
6
7
|
textKey?: string;
|
|
7
8
|
img?: string;
|
|
8
9
|
scale?: number;
|
|
9
10
|
iconColor?: string;
|
|
11
|
+
/** 圆点填充颜色。未设置 img 时生效,与 circleRadius 搭配绘制纯色圆点。 */
|
|
12
|
+
circleColor?: string;
|
|
13
|
+
/** 圆点半径(像素),默认 6。仅在未设置 img 时生效。 */
|
|
14
|
+
circleRadius?: number;
|
|
10
15
|
}
|
|
11
16
|
export interface PointData {
|
|
12
17
|
lgtd: number;
|
|
13
18
|
lttd: number;
|
|
14
19
|
[key: string]: unknown;
|
|
15
20
|
}
|
|
21
|
+
/** *********************点 JSON 统一输入类型*********************/
|
|
22
|
+
export type PointJSONInput = PointData[] | MapJSONData | FeatureData | {
|
|
23
|
+
type: 'Point';
|
|
24
|
+
coordinates: number[];
|
|
25
|
+
} | {
|
|
26
|
+
type: 'MultiPoint';
|
|
27
|
+
coordinates: number[][];
|
|
28
|
+
};
|
|
16
29
|
export interface ClusterOptions extends PointOptions {
|
|
17
30
|
distance?: number;
|
|
18
31
|
minDistance?: number;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GeoJSON 数据标准化工具。
|
|
3
|
+
*
|
|
4
|
+
* 本模块借鉴 mapshaper 对地理数据输入的统一处理思路,
|
|
5
|
+
* 但仅提供轻量的点数据标准化能力,不包含拓扑简化、dissolve、clip/erase 等 GIS 编辑功能。
|
|
6
|
+
* 参见 https://github.com/mbloch/mapshaper (MPL-2.0, Node >=20.11)。
|
|
7
|
+
*/
|
|
8
|
+
import type { PointData, PointJSONInput } from '../types';
|
|
9
|
+
import type { FeatureData } from '../types';
|
|
10
|
+
import type { AddGeoJSONInput, GeoJSONGeometryType, GeoJSONGroupBy } from '../types';
|
|
11
|
+
/** *********************类型定义*********************/
|
|
12
|
+
/**
|
|
13
|
+
* 点 API 统一输入类型。
|
|
14
|
+
* 支持 PointData 数组、GeoJSON FeatureCollection、单个 Feature、
|
|
15
|
+
* 以及裸 GeoJSON Point / MultiPoint geometry 对象。
|
|
16
|
+
*/
|
|
17
|
+
export type { PointJSONInput };
|
|
18
|
+
/** *********************公开 API*********************/
|
|
19
|
+
/**
|
|
20
|
+
* 将多种形态的点数据输入统一标准化为 `PointData[]`。
|
|
21
|
+
*
|
|
22
|
+
* 支持的输入形态:
|
|
23
|
+
* - `PointData[]`:原样返回(深拷贝后过滤非法坐标)
|
|
24
|
+
* - GeoJSON `FeatureCollection`:遍历 features,提取 Point / MultiPoint geometry
|
|
25
|
+
* - 单个 GeoJSON `Feature`:提取其 Point 或 MultiPoint geometry
|
|
26
|
+
* - 裸 `Point` geometry:转为单元素 PointData 数组
|
|
27
|
+
* - 裸 `MultiPoint` geometry:拆成多个 PointData
|
|
28
|
+
*
|
|
29
|
+
* 过滤规则:
|
|
30
|
+
* - 非 Point / MultiPoint geometry 的 Feature 会被跳过
|
|
31
|
+
* - 坐标含 NaN / Infinity / 缺失的点会被跳过
|
|
32
|
+
* - null / undefined 输入返回空数组
|
|
33
|
+
*
|
|
34
|
+
* @param input 任意兼容的点数据输入
|
|
35
|
+
* @returns 标准化后的 PointData 数组
|
|
36
|
+
*/
|
|
37
|
+
export declare function normalizePointData(input: PointJSONInput | null | undefined): PointData[];
|
|
38
|
+
/** *********************GeoJSON 分组处理*********************/
|
|
39
|
+
/**
|
|
40
|
+
* 将 GeoJSON geometry 类型归类为简化的三大类。
|
|
41
|
+
* 无法识别的类型返回 null。
|
|
42
|
+
*/
|
|
43
|
+
export declare function classifyGeometryType(geometryType: string): GeoJSONGeometryType | null;
|
|
44
|
+
/**
|
|
45
|
+
* 将 addGeoJSON 的多种输入形态统一标准化为带 datasetKey 的 FeatureData 数组。
|
|
46
|
+
*
|
|
47
|
+
* - 单个 JSON → datasetKey 为 `'default'`
|
|
48
|
+
* - 数组 → datasetKey 为字符串索引 `'0'`, `'1'`, ...
|
|
49
|
+
* - `Record<string, json>` → datasetKey 为 key
|
|
50
|
+
*/
|
|
51
|
+
export declare function normalizeGeoJSONInputs(data: AddGeoJSONInput | null | undefined): Array<{
|
|
52
|
+
datasetKey: string;
|
|
53
|
+
features: FeatureData[];
|
|
54
|
+
}>;
|
|
55
|
+
/**
|
|
56
|
+
* 按 groupBy 和几何类型将 FeatureData 拆分到不同分组。
|
|
57
|
+
*
|
|
58
|
+
* - 未配置 groupBy 时,每个 datasetKey 成为一个组
|
|
59
|
+
* - 配置 groupBy 字符串时,从 properties 中取该字段值作为 groupKey
|
|
60
|
+
* - 配置 groupBy 回调时,调用回调获取 groupKey
|
|
61
|
+
* - groupKey 取不到时回退到 datasetKey
|
|
62
|
+
*/
|
|
63
|
+
/**
|
|
64
|
+
* 附加了 datasetKey 元数据的 FeatureData。
|
|
65
|
+
* 用于在 splitByGroupAndGeometry 后保留每个 feature 来源信息。
|
|
66
|
+
*/
|
|
67
|
+
export type FeatureWithDatasetKey = FeatureData & {
|
|
68
|
+
_datasetKey: string;
|
|
69
|
+
};
|
|
70
|
+
export declare function splitByGroupAndGeometry(normalized: Array<{
|
|
71
|
+
datasetKey: string;
|
|
72
|
+
features: FeatureData[];
|
|
73
|
+
}>, groupBy?: GeoJSONGroupBy): Record<string, {
|
|
74
|
+
point: FeatureWithDatasetKey[];
|
|
75
|
+
line: FeatureWithDatasetKey[];
|
|
76
|
+
polygon: FeatureWithDatasetKey[];
|
|
77
|
+
}>;
|