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.
- package/CHANGELOG.md +32 -0
- package/MyOl.d.ts +13 -0
- package/MyOl.js +72 -30
- package/README.md +43 -2
- package/core/geojson/GeoJSONRenderer.d.ts +30 -0
- package/core/geojson/GeoJSONRenderer.js +252 -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/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/MIGRATION-3.0.md +24 -0
- package/docs/Point.md +64 -9
- package/index.d.ts +3 -1
- package/index.js +2 -0
- 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/Line.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import GeoJSON from "ol/format/GeoJSON";
|
|
2
2
|
import VectorLayer from "ol/layer/Vector";
|
|
3
3
|
import VectorSource from "ol/source/Vector";
|
|
4
|
-
import { ErrorHandler } from "../../utils/ErrorHandler";
|
|
4
|
+
import { ErrorHandler, ErrorType } from "../../utils/ErrorHandler";
|
|
5
5
|
import ProjectionUtils from "../../utils/ProjectionUtils";
|
|
6
6
|
import ValidationUtils from "../../utils/ValidationUtils";
|
|
7
7
|
import { ConfigManager, MapTools } from "../map";
|
|
@@ -98,7 +98,7 @@ export default class Line {
|
|
|
98
98
|
ValidationUtils.validateNonEmptyString(url, 'Line url is required');
|
|
99
99
|
const response = await fetch(url);
|
|
100
100
|
if (!response.ok) {
|
|
101
|
-
throw
|
|
101
|
+
throw ErrorHandler.getInstance().createAndHandleError(`Failed to fetch line GeoJSON: ${response.status}`, ErrorType.DATA_ERROR);
|
|
102
102
|
}
|
|
103
103
|
const json = await response.json();
|
|
104
104
|
return this.addLine(json, options);
|
|
@@ -134,11 +134,11 @@ export default class Line {
|
|
|
134
134
|
ValidationUtils.validateNonEmptyString(url, 'Flow line url is required');
|
|
135
135
|
const response = await fetch(url);
|
|
136
136
|
if (!response.ok) {
|
|
137
|
-
throw
|
|
137
|
+
throw ErrorHandler.getInstance().createAndHandleError(`Failed to fetch flow line data: ${response.status}`, ErrorType.DATA_ERROR);
|
|
138
138
|
}
|
|
139
139
|
const jsonData = await response.json();
|
|
140
140
|
if (!jsonData || typeof jsonData !== 'object') {
|
|
141
|
-
throw
|
|
141
|
+
throw ErrorHandler.getInstance().createAndHandleError('Flow line JSON data is invalid', ErrorType.DATA_ERROR);
|
|
142
142
|
}
|
|
143
143
|
return this.addFlowLine(jsonData, mergedOptions);
|
|
144
144
|
}
|
|
@@ -93,7 +93,7 @@ export default class MapBaseLayers {
|
|
|
93
93
|
*/
|
|
94
94
|
initTiandituLayers() {
|
|
95
95
|
if (!this.options.token) {
|
|
96
|
-
throw
|
|
96
|
+
throw ErrorHandler.getInstance().createAndHandleError('Token is required for Tianditu layers', ErrorType.MAP_ERROR);
|
|
97
97
|
}
|
|
98
98
|
const { token, zIndex = ConfigManager.TIANDITU_CONFIG.DEFAULT_ZINDEX } = this.options;
|
|
99
99
|
try {
|
|
@@ -113,7 +113,7 @@ export default class MapBaseLayers {
|
|
|
113
113
|
*/
|
|
114
114
|
initAnnotationLayer() {
|
|
115
115
|
if (!this.options.token) {
|
|
116
|
-
throw
|
|
116
|
+
throw ErrorHandler.getInstance().createAndHandleError('请配置token后才能使用天地图注记', ErrorType.MAP_ERROR);
|
|
117
117
|
}
|
|
118
118
|
const { token, zIndex = ConfigManager.TIANDITU_CONFIG.DEFAULT_ZINDEX } = this.options;
|
|
119
119
|
this.loadDefaultAnnotationLayer(token, zIndex);
|
|
@@ -228,10 +228,10 @@ export default class MapBaseLayers {
|
|
|
228
228
|
switchAnnotationLayer(annotationType) {
|
|
229
229
|
try {
|
|
230
230
|
if (!this.options.token) {
|
|
231
|
-
throw
|
|
231
|
+
throw ErrorHandler.getInstance().createAndHandleError('Token is required for annotation layer', ErrorType.MAP_ERROR);
|
|
232
232
|
}
|
|
233
233
|
if (!this.options.annotation) {
|
|
234
|
-
throw
|
|
234
|
+
throw ErrorHandler.getInstance().createAndHandleError('Annotation is not enabled in options', ErrorType.MAP_ERROR);
|
|
235
235
|
}
|
|
236
236
|
const baseZIndex = this.options.zIndex ?? ConfigManager.TIANDITU_CONFIG.DEFAULT_ZINDEX;
|
|
237
237
|
this.setAnnotationLayer(annotationType, this.options.token, baseZIndex);
|
|
@@ -322,7 +322,7 @@ export default class MapBaseLayers {
|
|
|
322
322
|
addAnnotationLayer(options) {
|
|
323
323
|
try {
|
|
324
324
|
if (!this.options.token) {
|
|
325
|
-
throw
|
|
325
|
+
throw ErrorHandler.getInstance().createAndHandleError('Token is required for annotation layer', ErrorType.MAP_ERROR);
|
|
326
326
|
}
|
|
327
327
|
return MapBaseLayers.addAnnotationLayer(this.map, {
|
|
328
328
|
...options,
|
|
@@ -516,10 +516,10 @@ export default class MapBaseLayers {
|
|
|
516
516
|
static getTiandiTuLayer(options) {
|
|
517
517
|
try {
|
|
518
518
|
if (!options.token) {
|
|
519
|
-
throw
|
|
519
|
+
throw ErrorHandler.getInstance().createAndHandleError('Token is required for Tianditu layer', ErrorType.MAP_ERROR);
|
|
520
520
|
}
|
|
521
521
|
if (!options.type) {
|
|
522
|
-
throw
|
|
522
|
+
throw ErrorHandler.getInstance().createAndHandleError('Layer type is required for Tianditu layer', ErrorType.VALIDATION_ERROR);
|
|
523
523
|
}
|
|
524
524
|
return new TileLayer({
|
|
525
525
|
source: new XYZ({
|
|
@@ -542,10 +542,10 @@ export default class MapBaseLayers {
|
|
|
542
542
|
static createAnnotationLayer(options) {
|
|
543
543
|
try {
|
|
544
544
|
if (!options.token) {
|
|
545
|
-
throw
|
|
545
|
+
throw ErrorHandler.getInstance().createAndHandleError('Token is required for annotation layer', ErrorType.MAP_ERROR);
|
|
546
546
|
}
|
|
547
547
|
if (!options.type) {
|
|
548
|
-
throw
|
|
548
|
+
throw ErrorHandler.getInstance().createAndHandleError('Annotation type is required for annotation layer', ErrorType.VALIDATION_ERROR);
|
|
549
549
|
}
|
|
550
550
|
return new TileLayer({
|
|
551
551
|
source: new XYZ({
|
|
@@ -569,7 +569,7 @@ export default class MapBaseLayers {
|
|
|
569
569
|
try {
|
|
570
570
|
ErrorHandler.validateMap(map);
|
|
571
571
|
if (!options.token) {
|
|
572
|
-
throw
|
|
572
|
+
throw ErrorHandler.getInstance().createAndHandleError('Token is required for annotation layer', ErrorType.MAP_ERROR);
|
|
573
573
|
}
|
|
574
574
|
const layer = MapBaseLayers.createAnnotationLayer({
|
|
575
575
|
type: options.type,
|
|
@@ -601,7 +601,7 @@ export default class MapBaseLayers {
|
|
|
601
601
|
ValidationUtils.validatePositiveNumber(length, 'Valid length is required for tile grid');
|
|
602
602
|
const projection = getProjection('EPSG:4326');
|
|
603
603
|
if (!projection) {
|
|
604
|
-
throw
|
|
604
|
+
throw ErrorHandler.getInstance().createAndHandleError('Failed to get EPSG:4326 projection', ErrorType.MAP_ERROR);
|
|
605
605
|
}
|
|
606
606
|
const projectionExtent = projection.getExtent();
|
|
607
607
|
const size = getWidth(projectionExtent) / 256;
|
package/core/map/MapTools.js
CHANGED
|
@@ -31,7 +31,7 @@ class MapTools {
|
|
|
31
31
|
*/
|
|
32
32
|
getLayerByLayerName(layerName) {
|
|
33
33
|
if (!this.map) {
|
|
34
|
-
throw
|
|
34
|
+
throw ErrorHandler.getInstance().createAndHandleError('Map instance is not available', ErrorType.MAP_ERROR);
|
|
35
35
|
}
|
|
36
36
|
return MapTools.getLayerByLayerName(this.map, layerName);
|
|
37
37
|
}
|
|
@@ -64,7 +64,7 @@ class MapTools {
|
|
|
64
64
|
}
|
|
65
65
|
catch (error) {
|
|
66
66
|
ErrorHandler.getInstance().error('Error getting layers:', error);
|
|
67
|
-
throw
|
|
67
|
+
throw ErrorHandler.getInstance().createAndHandleError('Failed to retrieve layers from map', ErrorType.LAYER_ERROR);
|
|
68
68
|
}
|
|
69
69
|
return targetLayer;
|
|
70
70
|
}
|
|
@@ -144,7 +144,7 @@ class MapTools {
|
|
|
144
144
|
*/
|
|
145
145
|
clipMap(data) {
|
|
146
146
|
if (!this.map) {
|
|
147
|
-
throw
|
|
147
|
+
throw ErrorHandler.getInstance().createAndHandleError('Map instance is not available', ErrorType.MAP_ERROR);
|
|
148
148
|
}
|
|
149
149
|
MapTools.clipMap(this.map, data);
|
|
150
150
|
}
|
|
@@ -155,7 +155,7 @@ class MapTools {
|
|
|
155
155
|
*/
|
|
156
156
|
static clipMap(map, data) {
|
|
157
157
|
if (!map) {
|
|
158
|
-
throw
|
|
158
|
+
throw ErrorHandler.getInstance().createAndHandleError('Map instance is required', ErrorType.MAP_ERROR);
|
|
159
159
|
}
|
|
160
160
|
map.getLayers().getArray().forEach(layer => {
|
|
161
161
|
try {
|
|
@@ -173,7 +173,7 @@ class MapTools {
|
|
|
173
173
|
*/
|
|
174
174
|
removeLayer(layerName) {
|
|
175
175
|
if (!this.map) {
|
|
176
|
-
throw
|
|
176
|
+
throw ErrorHandler.getInstance().createAndHandleError('Map instance is not available', ErrorType.MAP_ERROR);
|
|
177
177
|
}
|
|
178
178
|
MapTools.removeLayer(this.map, layerName);
|
|
179
179
|
}
|
|
@@ -185,7 +185,7 @@ class MapTools {
|
|
|
185
185
|
*/
|
|
186
186
|
static removeLayer(map, layerName) {
|
|
187
187
|
if (!map) {
|
|
188
|
-
throw
|
|
188
|
+
throw ErrorHandler.getInstance().createAndHandleError('Map instance is required', ErrorType.MAP_ERROR);
|
|
189
189
|
}
|
|
190
190
|
try {
|
|
191
191
|
const layers = MapTools.getLayerByLayerName(map, layerName);
|
|
@@ -195,7 +195,7 @@ class MapTools {
|
|
|
195
195
|
}
|
|
196
196
|
catch (error) {
|
|
197
197
|
ErrorHandler.getInstance().error('Error removing layers:', error);
|
|
198
|
-
throw
|
|
198
|
+
throw ErrorHandler.getInstance().createAndHandleError('Failed to remove layers from map', ErrorType.LAYER_ERROR);
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
/**
|
|
@@ -206,7 +206,7 @@ class MapTools {
|
|
|
206
206
|
*/
|
|
207
207
|
setLayerVisible(layerName, visible) {
|
|
208
208
|
if (!this.map) {
|
|
209
|
-
throw
|
|
209
|
+
throw ErrorHandler.getInstance().createAndHandleError('Map instance is not available', ErrorType.MAP_ERROR);
|
|
210
210
|
}
|
|
211
211
|
MapTools.setLayerVisible(this.map, layerName, visible);
|
|
212
212
|
}
|
|
@@ -221,7 +221,7 @@ class MapTools {
|
|
|
221
221
|
*/
|
|
222
222
|
locationAction(lgtd, lttd, zoom = 20, duration = 3000, projection) {
|
|
223
223
|
if (!this.map) {
|
|
224
|
-
throw
|
|
224
|
+
throw ErrorHandler.getInstance().createAndHandleError('Map instance is not available', ErrorType.MAP_ERROR);
|
|
225
225
|
}
|
|
226
226
|
const hasProjection = !!projection?.dataProjection || !!projection?.featureProjection;
|
|
227
227
|
const isValidCoordinate = hasProjection
|
|
@@ -274,7 +274,7 @@ class MapTools {
|
|
|
274
274
|
*/
|
|
275
275
|
static fitByData(map, jsonData, fitOptions) {
|
|
276
276
|
if (!map) {
|
|
277
|
-
throw
|
|
277
|
+
throw ErrorHandler.getInstance().createAndHandleError('Map instance is required', ErrorType.MAP_ERROR);
|
|
278
278
|
}
|
|
279
279
|
if (!jsonData) {
|
|
280
280
|
return false;
|
|
@@ -303,7 +303,7 @@ class MapTools {
|
|
|
303
303
|
*/
|
|
304
304
|
static fitToLayers(map, layerNameOrLayers, fitOptions) {
|
|
305
305
|
if (!map) {
|
|
306
|
-
throw
|
|
306
|
+
throw ErrorHandler.getInstance().createAndHandleError('Map instance is required', ErrorType.MAP_ERROR);
|
|
307
307
|
}
|
|
308
308
|
const layers = typeof layerNameOrLayers === "string"
|
|
309
309
|
? MapTools.getLayerByLayerName(map, layerNameOrLayers)
|
|
@@ -365,13 +365,13 @@ class MapTools {
|
|
|
365
365
|
*/
|
|
366
366
|
MapTools.setLayerVisible = (map, layerName, visible) => {
|
|
367
367
|
if (!map) {
|
|
368
|
-
throw
|
|
368
|
+
throw ErrorHandler.getInstance().createAndHandleError('Map instance is required', ErrorType.MAP_ERROR);
|
|
369
369
|
}
|
|
370
370
|
if (typeof layerName !== 'string') {
|
|
371
|
-
throw
|
|
371
|
+
throw ErrorHandler.getInstance().createAndHandleError('Layer name must be a string', ErrorType.VALIDATION_ERROR);
|
|
372
372
|
}
|
|
373
373
|
if (typeof visible !== 'boolean') {
|
|
374
|
-
throw
|
|
374
|
+
throw ErrorHandler.getInstance().createAndHandleError('Visible parameter must be a boolean', ErrorType.VALIDATION_ERROR);
|
|
375
375
|
}
|
|
376
376
|
try {
|
|
377
377
|
const layers = MapTools.getLayerByLayerName(map, layerName);
|
|
@@ -381,7 +381,7 @@ MapTools.setLayerVisible = (map, layerName, visible) => {
|
|
|
381
381
|
}
|
|
382
382
|
catch (error) {
|
|
383
383
|
ErrorHandler.getInstance().error('Error setting layer visibility:', error);
|
|
384
|
-
throw
|
|
384
|
+
throw ErrorHandler.getInstance().createAndHandleError('Failed to set layer visibility', ErrorType.LAYER_ERROR);
|
|
385
385
|
}
|
|
386
386
|
};
|
|
387
387
|
export default MapTools;
|
|
@@ -7,7 +7,7 @@ import { Vector as VectorLayer } from 'ol/layer.js';
|
|
|
7
7
|
import { getArea, getLength } from 'ol/sphere.js';
|
|
8
8
|
import { unByKey } from 'ol/Observable.js';
|
|
9
9
|
import ValidationUtils from '../../utils/ValidationUtils';
|
|
10
|
-
import { ErrorHandler } from '../../utils/ErrorHandler';
|
|
10
|
+
import { ErrorHandler, ErrorType } from '../../utils/ErrorHandler';
|
|
11
11
|
/**
|
|
12
12
|
* 测量工具处理类
|
|
13
13
|
* 提供距离和面积测量功能
|
|
@@ -174,7 +174,7 @@ export default class MeasureHandler {
|
|
|
174
174
|
}
|
|
175
175
|
catch (error) {
|
|
176
176
|
ErrorHandler.getInstance().error('Error starting measurement:', error);
|
|
177
|
-
throw
|
|
177
|
+
throw ErrorHandler.getInstance().createAndHandleError('Failed to start measurement', ErrorType.MAP_ERROR);
|
|
178
178
|
}
|
|
179
179
|
this._draw = new Draw({
|
|
180
180
|
source: this.source,
|
package/core/point/Point.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import Map from "ol/Map";
|
|
2
|
+
import { Style } from "ol/style";
|
|
2
3
|
import VectorLayer from "ol/layer/Vector";
|
|
3
4
|
import VectorSource from "ol/source/Vector";
|
|
4
5
|
import Overlay from 'ol/Overlay';
|
|
5
6
|
import { PointOptions, ClusterOptions, PointData, VueTemplatePointInstance, TwinkleItem, PulsePointOptions, PulsePointLayerHandle, LayerHandle, ControlHandle } from '../../types';
|
|
7
|
+
import { type PointJSONInput } from '../../utils/GeoJSONProcessor';
|
|
6
8
|
export default class Point {
|
|
7
9
|
private map;
|
|
8
10
|
/** 由本实例创建的纯图层(addPoint / addClusterPoint)。destroyAll 时统一移除。 */
|
|
@@ -36,13 +38,13 @@ export default class Point {
|
|
|
36
38
|
*/
|
|
37
39
|
private createIconStyle;
|
|
38
40
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
+
* 创建点样式。
|
|
42
|
+
* 供内部 createPointLayer 和 addGeoJSON 的 styleByProperties 回调使用。
|
|
41
43
|
* @param options 选项
|
|
42
|
-
* @param item
|
|
44
|
+
* @param item 数据项(可选,用于 textKey 文本提取)
|
|
43
45
|
* @returns 样式对象
|
|
44
46
|
*/
|
|
45
|
-
|
|
47
|
+
createPointStyle(options: PointOptions | ClusterOptions, item?: PointData): Style;
|
|
46
48
|
/**
|
|
47
49
|
* 创建集群样式
|
|
48
50
|
* @private
|
|
@@ -72,11 +74,11 @@ export default class Point {
|
|
|
72
74
|
/** *********************创建聚合点图层*********************/
|
|
73
75
|
private createClusterPointLayer;
|
|
74
76
|
/** *********************添加普通点*********************/
|
|
75
|
-
addPoint(pointData:
|
|
77
|
+
addPoint(pointData: PointJSONInput, options: PointOptions & {
|
|
76
78
|
layerName: string;
|
|
77
79
|
}): LayerHandle<VectorLayer<VectorSource>> | null;
|
|
78
80
|
/** *********************添加聚合点*********************/
|
|
79
|
-
addClusterPoint(pointData:
|
|
81
|
+
addClusterPoint(pointData: PointJSONInput, options: ClusterOptions & {
|
|
80
82
|
layerName: string;
|
|
81
83
|
}): LayerHandle<VectorLayer<VectorSource>> | null;
|
|
82
84
|
/** @internal 把 VectorLayer 包成 LayerHandle 的内部工具。 */
|
|
@@ -87,7 +89,7 @@ export default class Point {
|
|
|
87
89
|
* 与 addDomPoint 不同,该方法使用 VectorLayer 批量渲染点位,并通过单个
|
|
88
90
|
* requestAnimationFrame 驱动闪烁圈,适合村庄预警等大量点位场景。
|
|
89
91
|
*/
|
|
90
|
-
addPulsePointLayer(pointData:
|
|
92
|
+
addPulsePointLayer(pointData: PointJSONInput, options: PulsePointOptions & {
|
|
91
93
|
layerName: string;
|
|
92
94
|
}): PulsePointLayerHandle | null;
|
|
93
95
|
/**
|
|
@@ -129,13 +131,14 @@ export default class Point {
|
|
|
129
131
|
getPoints: () => VueTemplatePointInstance[];
|
|
130
132
|
};
|
|
131
133
|
/**
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
134
|
+
* 地图定位
|
|
135
|
+
* @deprecated 请使用 MapTools.locationAction 方法代替
|
|
136
|
+
* @param lgtd 经度
|
|
137
|
+
* @param lttd 纬度
|
|
138
|
+
* @param zoom 缩放级别
|
|
139
|
+
* @param duration 动画时长
|
|
140
|
+
* @param projection
|
|
141
|
+
*/
|
|
139
142
|
locationAction(lgtd: number, lttd: number, zoom?: number, duration?: number, projection?: {
|
|
140
143
|
dataProjection?: string;
|
|
141
144
|
featureProjection?: string;
|
package/core/point/Point.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import Feature from "ol/Feature";
|
|
2
2
|
import { Point as olPoint } from "ol/geom";
|
|
3
|
-
import { Text, Style, Fill, Stroke, Icon } from "ol/style";
|
|
3
|
+
import { Text, Style, Fill, Stroke, Icon, Circle as CircleStyle } from "ol/style";
|
|
4
4
|
import VectorLayer from "ol/layer/Vector";
|
|
5
5
|
import VectorSource from "ol/source/Vector";
|
|
6
|
+
import { normalizePointData } from '../../utils/GeoJSONProcessor';
|
|
6
7
|
import { VueTemplatePoint } from '../vue-template-point';
|
|
7
8
|
import ValidationUtils from '../../utils/ValidationUtils';
|
|
9
|
+
import { ErrorHandler, ErrorType } from '../../utils/ErrorHandler';
|
|
8
10
|
import ProjectionUtils from '../../utils/ProjectionUtils';
|
|
9
11
|
import { ConfigManager, MapTools } from "../map";
|
|
10
12
|
import PointClusterLayer from './PointClusterLayer';
|
|
@@ -93,10 +95,10 @@ export default class Point {
|
|
|
93
95
|
return new Icon(iconOptions);
|
|
94
96
|
}
|
|
95
97
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
+
* 创建点样式。
|
|
99
|
+
* 供内部 createPointLayer 和 addGeoJSON 的 styleByProperties 回调使用。
|
|
98
100
|
* @param options 选项
|
|
99
|
-
* @param item
|
|
101
|
+
* @param item 数据项(可选,用于 textKey 文本提取)
|
|
100
102
|
* @returns 样式对象
|
|
101
103
|
*/
|
|
102
104
|
createPointStyle(options, item) {
|
|
@@ -105,8 +107,16 @@ export default class Point {
|
|
|
105
107
|
style.text = this.createTextStyle(options, String(item[options.textKey] ?? ''));
|
|
106
108
|
}
|
|
107
109
|
if (options.img) {
|
|
110
|
+
// 图标样式优先
|
|
108
111
|
style.image = this.createIconStyle(options);
|
|
109
112
|
}
|
|
113
|
+
else if (options.circleColor || options.circleRadius) {
|
|
114
|
+
// 圆点样式:未设置 img 且提供了 circleColor 或 circleRadius 时生效
|
|
115
|
+
style.image = new CircleStyle({
|
|
116
|
+
radius: options.circleRadius ?? 6,
|
|
117
|
+
fill: new Fill({ color: options.circleColor ?? '#3399CC' }),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
110
120
|
return new Style(style);
|
|
111
121
|
}
|
|
112
122
|
/**
|
|
@@ -147,11 +157,12 @@ export default class Point {
|
|
|
147
157
|
*/
|
|
148
158
|
/** *********************创建普通点图层*********************/
|
|
149
159
|
createPointLayer(pointData, options) {
|
|
150
|
-
|
|
160
|
+
const normalized = normalizePointData(pointData);
|
|
161
|
+
if (!ValidationUtils.validatePointData(normalized)) {
|
|
151
162
|
return null;
|
|
152
163
|
}
|
|
153
164
|
const pointFeatureList = [];
|
|
154
|
-
|
|
165
|
+
normalized.forEach((item) => {
|
|
155
166
|
if (!ValidationUtils.validateCoordinates(item)) {
|
|
156
167
|
return;
|
|
157
168
|
}
|
|
@@ -190,10 +201,11 @@ export default class Point {
|
|
|
190
201
|
}
|
|
191
202
|
/** *********************创建聚合点图层*********************/
|
|
192
203
|
createClusterPointLayer(pointData, options) {
|
|
193
|
-
|
|
204
|
+
const normalized = normalizePointData(pointData);
|
|
205
|
+
if (!ValidationUtils.validatePointData(normalized)) {
|
|
194
206
|
return null;
|
|
195
207
|
}
|
|
196
|
-
const layer = PointClusterLayer.create(this.map,
|
|
208
|
+
const layer = PointClusterLayer.create(this.map, normalized, options, this.createClusterStyle.bind(this));
|
|
197
209
|
if (layer) {
|
|
198
210
|
this.trackLayer(layer);
|
|
199
211
|
}
|
|
@@ -233,10 +245,11 @@ export default class Point {
|
|
|
233
245
|
* requestAnimationFrame 驱动闪烁圈,适合村庄预警等大量点位场景。
|
|
234
246
|
*/
|
|
235
247
|
addPulsePointLayer(pointData, options) {
|
|
236
|
-
|
|
248
|
+
const normalized = normalizePointData(pointData);
|
|
249
|
+
if (!ValidationUtils.validatePointData(normalized)) {
|
|
237
250
|
return null;
|
|
238
251
|
}
|
|
239
|
-
const handle = PointPulseLayer.create(this.map,
|
|
252
|
+
const handle = PointPulseLayer.create(this.map, normalized, options);
|
|
240
253
|
this.trackDisposable(handle);
|
|
241
254
|
return handle;
|
|
242
255
|
}
|
|
@@ -250,15 +263,10 @@ export default class Point {
|
|
|
250
263
|
ValidationUtils.validateNonEmptyString(url, 'Point url is required');
|
|
251
264
|
const response = await fetch(url);
|
|
252
265
|
if (!response.ok) {
|
|
253
|
-
throw
|
|
266
|
+
throw ErrorHandler.getInstance().createAndHandleError(`Failed to fetch point data: ${response.status}`, ErrorType.DATA_ERROR);
|
|
254
267
|
}
|
|
255
268
|
const json = await response.json();
|
|
256
|
-
|
|
257
|
-
...f.properties,
|
|
258
|
-
lgtd: f.geometry?.coordinates?.[0],
|
|
259
|
-
lttd: f.geometry?.coordinates?.[1]
|
|
260
|
-
}));
|
|
261
|
-
return this.addPoint(pointData, options);
|
|
269
|
+
return this.addPoint(json, options);
|
|
262
270
|
}
|
|
263
271
|
/**
|
|
264
272
|
* P1-2:从 URL 加载点位数据并添加为高性能闪烁点图层。
|
|
@@ -267,15 +275,10 @@ export default class Point {
|
|
|
267
275
|
ValidationUtils.validateNonEmptyString(url, 'Pulse point url is required');
|
|
268
276
|
const response = await fetch(url);
|
|
269
277
|
if (!response.ok) {
|
|
270
|
-
throw
|
|
278
|
+
throw ErrorHandler.getInstance().createAndHandleError(`Failed to fetch pulse point data: ${response.status}`, ErrorType.DATA_ERROR);
|
|
271
279
|
}
|
|
272
280
|
const json = await response.json();
|
|
273
|
-
|
|
274
|
-
...f.properties,
|
|
275
|
-
lgtd: f.geometry?.coordinates?.[0],
|
|
276
|
-
lttd: f.geometry?.coordinates?.[1]
|
|
277
|
-
}));
|
|
278
|
-
return this.addPulsePointLayer(pointData, options);
|
|
281
|
+
return this.addPulsePointLayer(json, options);
|
|
279
282
|
}
|
|
280
283
|
/**
|
|
281
284
|
* 添加闪烁点
|
|
@@ -297,10 +300,10 @@ export default class Point {
|
|
|
297
300
|
*/
|
|
298
301
|
addVueTemplatePoint(pointDataList, template, options) {
|
|
299
302
|
if (!pointDataList || !Array.isArray(pointDataList) || pointDataList.length === 0) {
|
|
300
|
-
throw
|
|
303
|
+
throw ErrorHandler.getInstance().createAndHandleError('Valid point info list is required', ErrorType.VALIDATION_ERROR);
|
|
301
304
|
}
|
|
302
305
|
if (!template) {
|
|
303
|
-
throw
|
|
306
|
+
throw ErrorHandler.getInstance().createAndHandleError('Vue template is required', ErrorType.VALIDATION_ERROR);
|
|
304
307
|
}
|
|
305
308
|
try {
|
|
306
309
|
if (!this.vueTemplatePoint) {
|
|
@@ -311,17 +314,18 @@ export default class Point {
|
|
|
311
314
|
return handle;
|
|
312
315
|
}
|
|
313
316
|
catch (error) {
|
|
314
|
-
throw
|
|
317
|
+
throw ErrorHandler.getInstance().createAndHandleError(`Failed to create Vue template points: ${error}`, ErrorType.COMPONENT_ERROR);
|
|
315
318
|
}
|
|
316
319
|
}
|
|
317
320
|
/**
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
321
|
+
* 地图定位
|
|
322
|
+
* @deprecated 请使用 MapTools.locationAction 方法代替
|
|
323
|
+
* @param lgtd 经度
|
|
324
|
+
* @param lttd 纬度
|
|
325
|
+
* @param zoom 缩放级别
|
|
326
|
+
* @param duration 动画时长
|
|
327
|
+
* @param projection
|
|
328
|
+
*/
|
|
325
329
|
locationAction(lgtd, lttd, zoom = 20, duration = 3000, projection) {
|
|
326
330
|
return new MapTools(this.map).locationAction(lgtd, lttd, zoom, duration, projection);
|
|
327
331
|
}
|
package/core/polygon/Polygon.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import VectorLayer from "ol/layer/Vector";
|
|
3
3
|
import VectorSource from "ol/source/Vector";
|
|
4
4
|
import GeoJSON from "ol/format/GeoJSON";
|
|
5
|
-
import { ErrorHandler, InvalidGeoJSONError, LayerNotFoundError } from '../../utils/ErrorHandler';
|
|
5
|
+
import { ErrorHandler, ErrorType, InvalidGeoJSONError, LayerNotFoundError } from '../../utils/ErrorHandler';
|
|
6
6
|
import ProjectionUtils from '../../utils/ProjectionUtils';
|
|
7
7
|
import ValidationUtils from '../../utils/ValidationUtils';
|
|
8
8
|
import { ConfigManager, MapTools } from "../map";
|
|
@@ -25,7 +25,7 @@ export default class Polygon {
|
|
|
25
25
|
*/
|
|
26
26
|
this.managedLayers = new Set();
|
|
27
27
|
if (!map) {
|
|
28
|
-
throw
|
|
28
|
+
throw ErrorHandler.getInstance().createAndHandleError('Map instance is required', ErrorType.MAP_ERROR);
|
|
29
29
|
}
|
|
30
30
|
this.map = map;
|
|
31
31
|
}
|
|
@@ -161,7 +161,7 @@ export default class Polygon {
|
|
|
161
161
|
ValidationUtils.validateNonEmptyString(url, 'Polygon url is required');
|
|
162
162
|
const response = await fetch(url);
|
|
163
163
|
if (!response.ok) {
|
|
164
|
-
throw
|
|
164
|
+
throw ErrorHandler.getInstance().createAndHandleError(`Failed to fetch polygon GeoJSON: ${response.status}`, ErrorType.DATA_ERROR);
|
|
165
165
|
}
|
|
166
166
|
const json = await response.json();
|
|
167
167
|
return this.addPolygon(json, options);
|
|
@@ -191,7 +191,7 @@ export default class Polygon {
|
|
|
191
191
|
}
|
|
192
192
|
const layer = layers[0];
|
|
193
193
|
if (!(layer instanceof VectorLayer)) {
|
|
194
|
-
throw
|
|
194
|
+
throw ErrorHandler.getInstance().createAndHandleError(`Layer '${layerName}' is not a vector layer`, ErrorType.LAYER_ERROR);
|
|
195
195
|
}
|
|
196
196
|
const mergedOptions = {
|
|
197
197
|
textFont: '14px Calibri,sans-serif',
|
|
@@ -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) {
|