my-openlayer 3.0.2 → 3.1.1

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.
@@ -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 new Error('Valid point info list is required');
87
+ throw ErrorHandler.getInstance().createAndHandleError('Valid point info list is required', ErrorType.VALIDATION_ERROR);
88
88
  }
89
89
  if (!template) {
90
- throw new Error('Vue template is required');
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 new Error('Valid longitude and latitude are required for each point');
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 new Error(`Failed to create Vue template points: ${error}`);
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 new Error('Longitude and lttd must be numbers');
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 new Error('Vue is not available. Please ensure Vue is installed in your project.');
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 new Error(`Failed to create Vue app: ${error}`);
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 new Error('Cannot set visibility on destroyed DOM point');
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 new Error('Cannot update position on destroyed DOM point');
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 new Error('Cannot update props on destroyed DOM point');
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 new Error('Cannot set style on destroyed DOM point');
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 new Error('Cannot add class to destroyed DOM point');
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 new Error('Cannot remove class from destroyed DOM point');
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 {
@@ -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: PointData[], options: PointOptions & { layerName: string }): LayerHandle<VectorLayer<VectorSource>> | null
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: PointData[], options: ClusterOptions & { layerName: string }): LayerHandle<VectorLayer<VectorSource>> | null
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: PointData[], options: PulsePointOptions): PulsePointLayerHandle | null
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
@@ -11,8 +11,10 @@ export type { CustomProjectionRegistration } from './core/projection';
11
11
  export type { MapEventType, EventCallback, MapEventData } from './core/map/EventManager';
12
12
  export { ErrorHandler, MyOpenLayersError, ErrorType, LayerNotFoundError, InvalidGeoJSONError, ProjectionError } from './utils/ErrorHandler';
13
13
  export { default as ValidationUtils } from './utils/ValidationUtils';
14
+ export { normalizePointData } from './utils/GeoJSONProcessor';
15
+ export type { PointJSONInput } from './types';
14
16
  export type { BaseOptions, StyleOptions, TextOptions, LayerHandle, AnimatedLayerHandle } from './types';
15
17
  export type { PointOptions, LineOptions, FlowLineOptions, FlowLineLayerHandle, PolygonOptions, PulsePointOptions, PulsePointLayerHandle } from './types';
16
18
  export type { OptionsType } from './types';
17
- 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';
18
20
  export { VueTemplatePointState } from './types';
package/index.js CHANGED
@@ -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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "my-openlayer",
3
3
  "private": false,
4
- "version": "3.0.2",
4
+ "version": "3.1.1",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "main": "index.js",
@@ -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 {};
@@ -0,0 +1,4 @@
1
+ /**
2
+ * addGeoJSON 综合方法相关类型定义。
3
+ */
4
+ export {};
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
+ }>;