my-openlayer 2.4.10 → 2.5.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.
Files changed (119) hide show
  1. package/CHANGELOG.md +167 -265
  2. package/MyOl.d.ts +9 -9
  3. package/MyOl.js +17 -16
  4. package/README.md +217 -156
  5. package/core/line/Line.d.ts +40 -0
  6. package/core/line/Line.js +144 -0
  7. package/core/line/LineFeatureFactory.d.ts +17 -0
  8. package/core/line/LineFeatureFactory.js +75 -0
  9. package/core/line/LineFlowAnimator.d.ts +53 -0
  10. package/core/line/LineFlowAnimator.js +297 -0
  11. package/core/line/LineStyleFactory.d.ts +43 -0
  12. package/core/line/LineStyleFactory.js +135 -0
  13. package/core/{RiverLayerManager.d.ts → line/RiverLayerManager.d.ts} +2 -2
  14. package/core/{RiverLayerManager.js → line/RiverLayerManager.js} +3 -5
  15. package/core/line/index.d.ts +6 -0
  16. package/core/line/index.js +5 -0
  17. package/core/{ConfigManager.d.ts → map/ConfigManager.d.ts} +25 -1
  18. package/core/{ConfigManager.js → map/ConfigManager.js} +22 -1
  19. package/core/{EventManager.d.ts → map/EventManager.d.ts} +1 -1
  20. package/core/{EventManager.js → map/EventManager.js} +2 -2
  21. package/core/{MapBaseLayers.d.ts → map/MapBaseLayers.d.ts} +1 -1
  22. package/core/{MapBaseLayers.js → map/MapBaseLayers.js} +10 -12
  23. package/core/{MapTools.d.ts → map/MapTools.d.ts} +5 -2
  24. package/core/{MapTools.js → map/MapTools.js} +11 -5
  25. package/core/{MeasureHandler.d.ts → map/MeasureHandler.d.ts} +1 -1
  26. package/core/{MeasureHandler.js → map/MeasureHandler.js} +41 -41
  27. package/core/map/index.d.ts +5 -0
  28. package/core/map/index.js +5 -0
  29. package/core/{Point.d.ts → point/Point.d.ts} +13 -4
  30. package/core/{Point.js → point/Point.js} +24 -112
  31. package/core/point/PointClusterLayer.d.ts +10 -0
  32. package/core/point/PointClusterLayer.js +52 -0
  33. package/core/point/PointOverlay.d.ts +13 -0
  34. package/core/point/PointOverlay.js +57 -0
  35. package/core/point/PointPulseLayer.d.ts +13 -0
  36. package/core/point/PointPulseLayer.js +207 -0
  37. package/core/point/index.d.ts +4 -0
  38. package/core/point/index.js +4 -0
  39. package/core/{Polygon.d.ts → polygon/Polygon.d.ts} +4 -50
  40. package/core/polygon/Polygon.js +248 -0
  41. package/core/polygon/PolygonHeatmapLayer.d.ts +11 -0
  42. package/core/polygon/PolygonHeatmapLayer.js +40 -0
  43. package/core/polygon/PolygonImageLayer.d.ts +9 -0
  44. package/core/polygon/PolygonImageLayer.js +61 -0
  45. package/core/polygon/PolygonMaskLayer.d.ts +20 -0
  46. package/core/polygon/PolygonMaskLayer.js +107 -0
  47. package/core/polygon/PolygonStyleFactory.d.ts +12 -0
  48. package/core/polygon/PolygonStyleFactory.js +100 -0
  49. package/core/polygon/index.d.ts +5 -0
  50. package/core/polygon/index.js +5 -0
  51. package/core/{SelectHandler.d.ts → select/SelectHandler.d.ts} +2 -3
  52. package/core/{SelectHandler.js → select/SelectHandler.js} +4 -4
  53. package/core/select/index.d.ts +1 -0
  54. package/core/select/index.js +1 -0
  55. package/core/{VueTemplatePoint.d.ts → vue-template-point/VueTemplatePoint.d.ts} +1 -1
  56. package/core/{VueTemplatePoint.js → vue-template-point/VueTemplatePoint.js} +4 -4
  57. package/core/vue-template-point/index.d.ts +1 -0
  58. package/core/vue-template-point/index.js +1 -0
  59. package/docs/.vitepress/config.mts +57 -57
  60. package/docs/ConfigManager.md +71 -71
  61. package/docs/ErrorHandler.md +106 -106
  62. package/docs/EventManager.md +142 -142
  63. package/docs/Line.md +215 -187
  64. package/docs/MapBaseLayers.md +198 -198
  65. package/docs/MapTools.md +172 -172
  66. package/docs/MeasureHandler.md +87 -87
  67. package/docs/MyOl.md +247 -247
  68. package/docs/Point.md +233 -165
  69. package/docs/Polygon.md +241 -241
  70. package/docs/RiverLayerManager.md +187 -187
  71. package/docs/SelectHandler.md +147 -147
  72. package/docs/ValidationUtils.md +83 -83
  73. package/docs/VueTemplatePoint.md +214 -214
  74. package/docs/index.md +79 -78
  75. package/index.d.ts +11 -16
  76. package/index.js +7 -13
  77. package/package.json +11 -1
  78. package/types/base.d.ts +47 -0
  79. package/types/base.js +1 -0
  80. package/types/common.d.ts +59 -0
  81. package/types/common.js +1 -0
  82. package/types/index.d.ts +9 -0
  83. package/types/index.js +1 -0
  84. package/types/line.d.ts +41 -0
  85. package/types/line.js +1 -0
  86. package/types/map.d.ts +77 -0
  87. package/types/map.js +1 -0
  88. package/types/point.d.ts +54 -0
  89. package/types/point.js +1 -0
  90. package/types/polygon.d.ts +8 -0
  91. package/types/polygon.js +1 -0
  92. package/types/select.d.ts +25 -0
  93. package/types/select.js +1 -0
  94. package/types/vue-template-point.d.ts +54 -0
  95. package/{types.js → types/vue-template-point.js} +0 -3
  96. package/utils/ProjectionUtils.d.ts +28 -0
  97. package/utils/ProjectionUtils.js +34 -0
  98. package/utils/ValidationUtils.d.ts +33 -86
  99. package/utils/ValidationUtils.js +60 -165
  100. package/core/DomPoint.d.ts +0 -21
  101. package/core/DomPoint.js +0 -36
  102. package/core/Line.d.ts +0 -49
  103. package/core/Line.js +0 -114
  104. package/core/Polygon.js +0 -646
  105. package/docs/.vitepress/cache/deps/@theme_index.js +0 -275
  106. package/docs/.vitepress/cache/deps/@theme_index.js.map +0 -7
  107. package/docs/.vitepress/cache/deps/_metadata.json +0 -40
  108. package/docs/.vitepress/cache/deps/chunk-LW4I4DCF.js +0 -12542
  109. package/docs/.vitepress/cache/deps/chunk-LW4I4DCF.js.map +0 -7
  110. package/docs/.vitepress/cache/deps/chunk-Z5QSWKN2.js +0 -9719
  111. package/docs/.vitepress/cache/deps/chunk-Z5QSWKN2.js.map +0 -7
  112. package/docs/.vitepress/cache/deps/package.json +0 -3
  113. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +0 -4505
  114. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +0 -7
  115. package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +0 -583
  116. package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +0 -7
  117. package/docs/.vitepress/cache/deps/vue.js +0 -343
  118. package/docs/.vitepress/cache/deps/vue.js.map +0 -7
  119. package/types.d.ts +0 -372
package/core/Polygon.js DELETED
@@ -1,646 +0,0 @@
1
- "use strict";
2
- import VectorLayer from "ol/layer/Vector";
3
- import VectorSource from "ol/source/Vector";
4
- import GeoJSON from "ol/format/GeoJSON";
5
- import { Fill, Stroke, Style, Text } from "ol/style";
6
- import { Image as ImageLayer, Heatmap } from "ol/layer";
7
- import { LinearRing, Point } from "ol/geom";
8
- import { fromExtent } from "ol/geom/Polygon";
9
- import Feature from "ol/Feature";
10
- import ImageStatic from "ol/source/ImageStatic";
11
- import MapTools from "./MapTools";
12
- import { ErrorHandler } from '../utils/ErrorHandler';
13
- import { ValidationUtils } from '../utils/ValidationUtils';
14
- import { ConfigManager } from "./ConfigManager";
15
- /**
16
- * Polygon 类用于处理地图上的面要素操作
17
- * 包括添加多边形、边框、图片图层、热力图等功能
18
- */
19
- export default class Polygon {
20
- /**
21
- * 构造函数
22
- * @param map OpenLayers 地图实例
23
- */
24
- constructor(map) {
25
- if (!map) {
26
- throw new Error('Map instance is required');
27
- }
28
- this.map = map;
29
- }
30
- /**
31
- * 添加地图边框图层
32
- * @param data 图层数据,必须是有效的 GeoJSON 格式
33
- * @param options 图层配置选项
34
- * @returns 创建的图层实例
35
- * @throws 当数据格式无效时抛出错误
36
- */
37
- addBorderPolygon(data, options) {
38
- ValidationUtils.validateGeoJSONData(data);
39
- const mergedOptions = {
40
- fillColor: 'rgba(255, 255, 255, 0)',
41
- ...options
42
- };
43
- const layer = this.addPolygon(data, mergedOptions);
44
- if (mergedOptions.mask) {
45
- this.setOutLayer(data);
46
- }
47
- return layer;
48
- }
49
- /**
50
- * 从URL添加地图边框图层
51
- * @param url 数据URL
52
- * @param options 图层配置选项
53
- * @returns 创建的图层实例
54
- * @throws 当数据格式无效时抛出错误
55
- */
56
- addBorderPolygonByUrl(url, options) {
57
- const mergedOptions = {
58
- layerName: 'border',
59
- fillColor: 'rgba(255, 255, 255, 0)',
60
- ...options
61
- };
62
- const layer = this.addPolygonByUrl(url, mergedOptions);
63
- return layer;
64
- }
65
- /**
66
- * 添加多边形图层
67
- * @param dataJSON GeoJSON 数据
68
- * @param options 图层配置选项
69
- * @returns 创建的矢量图层
70
- * @throws 当数据格式无效时抛出错误
71
- */
72
- addPolygon(dataJSON, options) {
73
- ValidationUtils.validateGeoJSONData(dataJSON);
74
- const mergedOptions = {
75
- ...ConfigManager.DEFAULT_POLYGON_OPTIONS,
76
- ...options
77
- };
78
- // 如果指定了图层名称,先移除同名图层
79
- if (mergedOptions.layerName) {
80
- new MapTools(this.map).removeLayer(mergedOptions.layerName);
81
- }
82
- const format = new GeoJSON();
83
- // 优化:在解析 Feature 时直接注入 layerName,利用解析过程的遍历,避免解析后的二次循环
84
- if (mergedOptions.layerName) {
85
- const originalReadFeatureFromObject = format.readFeatureFromObject;
86
- format.readFeatureFromObject = function (object, options) {
87
- const feature = originalReadFeatureFromObject.call(this, object, options);
88
- feature.set('layerName', mergedOptions.layerName, true); // true 表示静默设置,不触发事件
89
- return feature;
90
- };
91
- }
92
- let features;
93
- try {
94
- features = format.readFeatures(dataJSON, mergedOptions.projectionOptOptions ?? {});
95
- }
96
- catch (error) {
97
- throw new Error(`Failed to parse GeoJSON data: ${error}`);
98
- }
99
- const layer = new VectorLayer({
100
- properties: {
101
- name: mergedOptions.layerName,
102
- layerName: mergedOptions.layerName
103
- },
104
- source: new VectorSource({ features }),
105
- style: this.createStyle(mergedOptions),
106
- zIndex: mergedOptions.zIndex
107
- });
108
- layer.setVisible(mergedOptions.visible);
109
- this.map.addLayer(layer);
110
- // 如果需要适应视图
111
- if (mergedOptions.fitView) {
112
- this.fitViewToLayer(layer);
113
- }
114
- return layer;
115
- }
116
- /**
117
- * 从URL添加多边形图层
118
- * @param url 数据URL
119
- * @param options 图层配置选项
120
- * @returns 创建的矢量图层
121
- * @throws 当数据格式无效时抛出错误
122
- */
123
- addPolygonByUrl(url, options) {
124
- const mergedOptions = {
125
- ...ConfigManager.DEFAULT_POLYGON_OPTIONS,
126
- ...options
127
- };
128
- // 如果指定了图层名称,先移除同名图层
129
- if (mergedOptions.layerName) {
130
- new MapTools(this.map).removeLayer(mergedOptions.layerName);
131
- }
132
- const format = new GeoJSON(mergedOptions.projectionOptOptions ?? {});
133
- // 优化:在解析 Feature 时直接注入 layerName,利用解析过程的遍历,避免解析后的二次循环
134
- if (mergedOptions.layerName) {
135
- const originalReadFeatureFromObject = format.readFeatureFromObject;
136
- format.readFeatureFromObject = function (object, options) {
137
- const feature = originalReadFeatureFromObject.call(this, object, options);
138
- feature.set('layerName', mergedOptions.layerName, true); // true 表示静默设置,不触发事件
139
- return feature;
140
- };
141
- }
142
- const source = new VectorSource({
143
- url,
144
- format
145
- });
146
- const layer = new VectorLayer({
147
- properties: {
148
- name: mergedOptions.layerName,
149
- layerName: mergedOptions.layerName
150
- },
151
- source,
152
- style: this.createStyle(mergedOptions),
153
- zIndex: mergedOptions.zIndex
154
- });
155
- layer.setVisible(mergedOptions.visible);
156
- this.map.addLayer(layer);
157
- // 如果需要适应视图
158
- if (mergedOptions.fitView) {
159
- source.once('featuresloadend', () => {
160
- this.fitViewToLayer(layer);
161
- });
162
- }
163
- return layer;
164
- }
165
- /**
166
- * 创建样式或样式函数
167
- * @param options 配置选项
168
- * @returns 样式或样式函数
169
- */
170
- //************* 创建样式功能块 *************//
171
- createStyle(options) {
172
- // 如果传入了自定义样式,直接使用
173
- if (options.style) {
174
- return options.style;
175
- }
176
- const withDefaultStroke = options.withDefaultStroke ?? true;
177
- const withDefaultFill = options.withDefaultFill ?? true;
178
- const strokeColor = options.strokeColor ?? (withDefaultStroke ? '#EBEEF5' : undefined);
179
- const strokeWidth = options.strokeWidth ?? 2;
180
- const staticFillColor = options.fillColor ?? (withDefaultFill ? 'rgba(255, 255, 255, 0)' : undefined);
181
- const stroke = strokeColor ? new Stroke({
182
- color: strokeColor,
183
- width: strokeWidth,
184
- lineDash: options.lineDash,
185
- lineDashOffset: options.lineDashOffset
186
- }) : undefined;
187
- // 预先创建基础样式(如果不需要基于feature动态计算fillColor)
188
- let baseStyle;
189
- if (!options.fillColorCallBack) {
190
- const fill = staticFillColor ? new Fill({ color: staticFillColor }) : undefined;
191
- if (stroke || fill) {
192
- baseStyle = new Style({
193
- stroke,
194
- fill
195
- });
196
- }
197
- }
198
- // 如果没有动态部分(没有回调且不显示文本),直接返回基础样式
199
- if (baseStyle && !options.textVisible) {
200
- return baseStyle;
201
- }
202
- // 返回样式函数
203
- return (feature, resolution) => {
204
- const styles = [];
205
- // 1. 处理几何样式
206
- if (baseStyle) {
207
- styles.push(baseStyle);
208
- }
209
- else {
210
- const fillColor = options.fillColorCallBack ? options.fillColorCallBack(feature) : staticFillColor;
211
- const fill = fillColor ? new Fill({ color: fillColor }) : undefined;
212
- if (stroke || fill) {
213
- styles.push(new Style({
214
- stroke,
215
- fill
216
- }));
217
- }
218
- }
219
- // 2. 处理文本样式
220
- if (options.textVisible) {
221
- const text = this.getFeatureText(feature, options);
222
- if (text) {
223
- styles.push(new Style({
224
- text: new Text({
225
- text,
226
- font: options.textFont,
227
- fill: new Fill({ color: options.textFillColor }),
228
- stroke: new Stroke({
229
- color: options.textStrokeColor,
230
- width: options.textStrokeWidth
231
- })
232
- })
233
- }));
234
- }
235
- }
236
- return styles;
237
- };
238
- }
239
- /**
240
- * 获取要素文本
241
- * @param feature 要素对象
242
- * @param options 配置选项
243
- * @returns 文本内容
244
- */
245
- getFeatureText(feature, options) {
246
- if (options.textCallBack) {
247
- return options.textCallBack(feature) || '';
248
- }
249
- if (options.textKey) {
250
- return feature.get(options.textKey) || '';
251
- }
252
- return '';
253
- }
254
- /**
255
- * 适应图层视图
256
- * @param layer 图层对象
257
- */
258
- fitViewToLayer(layer) {
259
- const extent = layer.getSource()?.getExtent();
260
- if (extent) {
261
- this.map.getView().fit(extent, { duration: 500 });
262
- }
263
- }
264
- /**
265
- * 根据数据数组更新某个面颜色
266
- * @param layerName 图层名称
267
- * @param colorObj 颜色映射对象,键为要素属性值,值为颜色字符串
268
- * @param options 配置项
269
- * @throws 当图层不存在时抛出错误
270
- */
271
- updateFeatureColor(layerName, colorObj, options) {
272
- ValidationUtils.validateLayerName(layerName);
273
- const layers = MapTools.getLayerByLayerName(this.map, layerName);
274
- if (layers.length === 0) {
275
- throw new Error(`Layer with name '${layerName}' not found`);
276
- }
277
- const layer = layers[0];
278
- if (!(layer instanceof VectorLayer)) {
279
- throw new Error(`Layer '${layerName}' is not a vector layer`);
280
- }
281
- const mergedOptions = {
282
- textFont: '14px Calibri,sans-serif',
283
- textFillColor: '#FFF',
284
- textStrokeWidth: 2,
285
- ...options
286
- };
287
- const features = layer.getSource()?.getFeatures();
288
- if (!features) {
289
- ErrorHandler.getInstance().warn(`No features found in layer '${layerName}'`);
290
- return;
291
- }
292
- features.forEach((feature) => {
293
- this.updateSingleFeatureColor(feature, colorObj, mergedOptions);
294
- });
295
- }
296
- /**
297
- * 更新单个要素的颜色
298
- * @param feature 要素对象
299
- * @param colorObj 颜色映射对象
300
- * @param options 配置选项
301
- */
302
- updateSingleFeatureColor(feature, colorObj, options) {
303
- const name = options?.textKey ? feature.get(options.textKey) : '';
304
- const withDefaultStroke = options?.withDefaultStroke ?? true;
305
- const withDefaultFill = options?.withDefaultFill ?? true;
306
- const strokeColor = options?.strokeColor ?? (withDefaultStroke ? '#EBEEF5' : undefined);
307
- const strokeWidth = options?.strokeWidth ?? 2;
308
- const defaultFillColor = 'rgba(255, 255, 255, 0.3)';
309
- const resolvedFillColor = options?.fillColor ?? (withDefaultFill ? defaultFillColor : undefined);
310
- const newColor = colorObj?.[name] || resolvedFillColor;
311
- const stroke = strokeColor ? new Stroke({
312
- color: strokeColor,
313
- width: strokeWidth
314
- }) : undefined;
315
- const fill = newColor ? new Fill({ color: newColor }) : undefined;
316
- const featureStyle = new Style({
317
- stroke,
318
- fill
319
- });
320
- // 添加文本样式
321
- if (options?.textVisible) {
322
- const text = this.getFeatureText(feature, options);
323
- if (text) {
324
- featureStyle.setText(new Text({
325
- text,
326
- font: options.textFont,
327
- fill: new Fill({ color: options.textFillColor }),
328
- stroke: new Stroke({
329
- color: options.textStrokeColor,
330
- width: options.textStrokeWidth
331
- })
332
- }));
333
- }
334
- }
335
- feature.setStyle(featureStyle);
336
- }
337
- /**
338
- * 设置外围蒙版图层
339
- *
340
- * 详细文档参考 https_blog.csdn.net/?url=https%3A%2F%2Fblog.csdn.net%2Fu012413551%2Farticle%2Fdetails%2F122739501
341
- *
342
- * @param data
343
- * @param options
344
- */
345
- setOutLayer(data, options) {
346
- /** geom转坐标数组 **/
347
- function getCoordsGroup(geom) {
348
- let group = []; //
349
- const geomType = geom.getType();
350
- if (geomType === 'LineString') {
351
- group.push(geom.getCoordinates());
352
- }
353
- else if (geomType === 'MultiLineString') {
354
- group = geom.getCoordinates();
355
- }
356
- else if (geomType === 'Polygon') {
357
- group = geom.getCoordinates();
358
- }
359
- else if (geomType === 'MultiPolygon') {
360
- geom.getPolygons().forEach((poly) => {
361
- const coords = poly.getCoordinates();
362
- group = group.concat(coords);
363
- });
364
- }
365
- else {
366
- ErrorHandler.getInstance().warn('暂时不支持的类型');
367
- }
368
- return group;
369
- }
370
- /** 擦除操作 - 创建遮罩多边形 **/
371
- function erase(geometries, view) {
372
- // 收集所有几何图形的坐标环
373
- let allParts = [];
374
- geometries.forEach(geom => {
375
- const parts = getCoordsGroup(geom);
376
- if (parts && parts.length > 0) {
377
- allParts = allParts.concat(parts);
378
- }
379
- });
380
- if (allParts.length === 0) {
381
- return null;
382
- }
383
- const extent = view.getProjection().getExtent();
384
- const polygonRing = fromExtent(extent);
385
- allParts.forEach((item) => {
386
- const linearRing = new LinearRing(item);
387
- polygonRing.appendLinearRing(linearRing);
388
- });
389
- return polygonRing;
390
- }
391
- // 遮罩样式
392
- const shadeStyle = new Style({
393
- fill: new Fill({
394
- color: options?.fillColor ?? 'rgba(0,27,59,0.8)'
395
- }),
396
- stroke: new Stroke({
397
- width: options?.strokeWidth ?? 1,
398
- color: options?.strokeColor ?? 'rgba(0,27,59,0.8)'
399
- })
400
- });
401
- // 遮罩数据源
402
- const vtSource = new VectorSource();
403
- // 遮罩图层
404
- const vtLayer = new VectorLayer({
405
- source: vtSource,
406
- style: shadeStyle,
407
- zIndex: options?.zIndex ?? 12
408
- });
409
- vtLayer.set('layerName', options?.layerName ?? 'outLayer');
410
- const features = new GeoJSON().readFeatures(data);
411
- // 收集所有要素的几何图形
412
- const geometries = [];
413
- features.forEach(feature => {
414
- const geometry = feature.getGeometry();
415
- if (geometry) {
416
- geometries.push(geometry);
417
- }
418
- });
419
- if (geometries.length > 0) {
420
- // 创建遮罩
421
- const polygon = erase(geometries, this.map.getView());
422
- if (polygon) {
423
- const feature = new Feature({
424
- geometry: polygon
425
- });
426
- vtSource.addFeature(feature);
427
- // 如果需要适应视图,计算所有几何图形的合并范围
428
- if (options?.extent) {
429
- let totalExtent = geometries[0].getExtent();
430
- for (let i = 1; i < geometries.length; i++) {
431
- // 注意:这里需要导入 extend 函数,或者使用简单的 extent 合并逻辑
432
- // 由于 openlayers 的 extent 是 [minx, miny, maxx, maxy]
433
- const ext = geometries[i].getExtent();
434
- totalExtent = [
435
- Math.min(totalExtent[0], ext[0]),
436
- Math.min(totalExtent[1], ext[1]),
437
- Math.max(totalExtent[2], ext[2]),
438
- Math.max(totalExtent[3], ext[3])
439
- ];
440
- }
441
- this.map.getView().fit(totalExtent);
442
- }
443
- }
444
- }
445
- this.map.addLayer(vtLayer);
446
- return vtLayer;
447
- }
448
- /**
449
- * 添加图片图层
450
- * @param imageData 图片数据,包含url和extent
451
- * @param options 配置项
452
- * @returns 创建的图片图层
453
- * @throws 当数据格式无效时抛出错误
454
- */
455
- addImageLayer(imageData, options) {
456
- // 检查是否允许空img(当存在layerName且存在同名图层时)
457
- const allowEmptyImg = !imageData.img && !!options?.layerName;
458
- ValidationUtils.validateImageData(imageData, allowEmptyImg);
459
- const mergedOptions = {
460
- ...ConfigManager.DEFAULT_IMAGE_OPTIONS,
461
- ...options
462
- };
463
- // 尝试更新现有图层
464
- if (mergedOptions.layerName) {
465
- const existingLayer = this.tryUpdateExistingImageLayer(imageData, mergedOptions);
466
- if (existingLayer) {
467
- return existingLayer;
468
- }
469
- }
470
- // 创建新图层
471
- return this.createNewImageLayer(imageData, mergedOptions);
472
- }
473
- /**
474
- * 尝试更新现有图层
475
- * @private
476
- */
477
- tryUpdateExistingImageLayer(imageData, options) {
478
- const existingLayers = MapTools.getLayerByLayerName(this.map, options.layerName);
479
- if (existingLayers.length === 0) {
480
- return null;
481
- }
482
- const existingLayer = existingLayers[0];
483
- // 如果没有extent,直接设置source为undefined
484
- if (!imageData.extent) {
485
- existingLayer.setSource(undefined);
486
- }
487
- else {
488
- // 创建新的source
489
- const url = imageData.img || existingLayer.getSource()?.getUrl() || '';
490
- const newSource = new ImageStatic({
491
- url,
492
- imageExtent: imageData.extent
493
- });
494
- existingLayer.setSource(newSource);
495
- }
496
- // 更新图层属性
497
- this.updateImageLayerProperties(existingLayer, options);
498
- return existingLayer;
499
- }
500
- /**
501
- * 创建新的图像图层
502
- * @private
503
- */
504
- createNewImageLayer(imageData, options) {
505
- let source = undefined;
506
- // 只有当extent存在时才创建ImageStatic source
507
- if (imageData.extent) {
508
- source = new ImageStatic({
509
- url: imageData.img || '',
510
- imageExtent: imageData.extent
511
- });
512
- }
513
- const imageLayer = new ImageLayer({
514
- source,
515
- opacity: options.opacity,
516
- visible: options.visible
517
- });
518
- this.configureImageLayer(imageLayer, options);
519
- return this.addImageLayerToMap(imageLayer, options);
520
- }
521
- /**
522
- * 更新图层属性
523
- * @private
524
- */
525
- updateImageLayerProperties(layer, options) {
526
- if (options.opacity !== undefined) {
527
- layer.setOpacity(options.opacity);
528
- }
529
- if (options.visible !== undefined) {
530
- layer.setVisible(options.visible);
531
- }
532
- if (options.zIndex !== undefined) {
533
- layer.setZIndex(options.zIndex);
534
- }
535
- }
536
- /**
537
- * 配置图层基本属性
538
- * @private
539
- */
540
- configureImageLayer(layer, options) {
541
- layer.set('name', options.layerName);
542
- layer.set('layerName', options.layerName);
543
- layer.setZIndex(options.zIndex);
544
- }
545
- /**
546
- * 添加图层到地图并应用裁剪
547
- * @private
548
- */
549
- addImageLayerToMap(layer, options) {
550
- if (options.mapClip && options.mapClipData) {
551
- const clippedLayer = MapTools.setMapClip(layer, options.mapClipData);
552
- this.map.addLayer(clippedLayer);
553
- return clippedLayer;
554
- }
555
- this.map.addLayer(layer);
556
- return layer;
557
- }
558
- /**
559
- * 添加热力图图层
560
- * @param pointData 点数据数组
561
- * @param options 热力图配置
562
- */
563
- addHeatmap(pointData, options) {
564
- // 只有在指定layerName时才移除已存在的同名图层
565
- if (options?.layerName) {
566
- new MapTools(this.map).removeLayer(options.layerName);
567
- }
568
- const mergedOptions = {
569
- ...ConfigManager.DEFAULT_HEATMAP_OPTIONS,
570
- ...options
571
- };
572
- const blur = mergedOptions.blur ?? ConfigManager.DEFAULT_HEATMAP_OPTIONS.blur;
573
- const radius = mergedOptions.radius ?? ConfigManager.DEFAULT_HEATMAP_OPTIONS.radius;
574
- const zIndex = mergedOptions.zIndex ?? ConfigManager.DEFAULT_HEATMAP_OPTIONS.zIndex;
575
- const opacity = mergedOptions.opacity ?? ConfigManager.DEFAULT_HEATMAP_OPTIONS.opacity;
576
- const heatmapLayer = new Heatmap({
577
- source: new VectorSource(),
578
- weight: function (fea) {
579
- return fea.get('weight');
580
- },
581
- blur,
582
- radius,
583
- zIndex,
584
- opacity,
585
- });
586
- // 只有在指定layerName时才设置layerName
587
- if (mergedOptions.layerName) {
588
- heatmapLayer.set('layerName', mergedOptions.layerName);
589
- }
590
- this.map.addLayer(heatmapLayer);
591
- const valueKey = mergedOptions.valueKey || ConfigManager.DEFAULT_HEATMAP_VALUE_KEY;
592
- const max = Math.max(...pointData.map(item => item[valueKey]));
593
- pointData.forEach((item) => {
594
- heatmapLayer?.getSource().addFeature(new Feature({
595
- geometry: new Point([item.lgtd, item.lttd]),
596
- weight: item[valueKey] / max //热力值范围是【0,1】;热力值计算 = 找出数据集中的最大值,然后用值除以最大值
597
- }));
598
- });
599
- return heatmapLayer;
600
- }
601
- /**
602
- * 添加遮罩图层
603
- * @param data GeoJSON格式的遮罩数据
604
- * @param options 配置项
605
- * @returns 创建的遮罩图层
606
- * @throws 当数据格式无效时抛出错误
607
- */
608
- addMaskLayer(data, options) {
609
- ValidationUtils.validateMaskData(data);
610
- const mergedOptions = {
611
- ...ConfigManager.DEFAULT_MASK_OPTIONS,
612
- ...options
613
- };
614
- let features;
615
- try {
616
- features = new GeoJSON().readFeatures(data);
617
- }
618
- catch (error) {
619
- throw new Error(`Invalid GeoJSON data: ${error}`);
620
- }
621
- if (!features || features.length === 0) {
622
- ErrorHandler.getInstance().warn('No features found in mask data');
623
- }
624
- const maskLayer = new VectorLayer({
625
- source: new VectorSource({ features }),
626
- style: new Style({
627
- fill: new Fill({
628
- color: mergedOptions.fillColor
629
- }),
630
- stroke: mergedOptions.strokeColor ? new Stroke({
631
- color: mergedOptions.strokeColor,
632
- width: mergedOptions.strokeWidth || 1
633
- }) : undefined
634
- }),
635
- opacity: mergedOptions.opacity,
636
- visible: mergedOptions.visible
637
- });
638
- maskLayer.set('layerName', mergedOptions.layerName);
639
- this.map.addLayer(maskLayer);
640
- return maskLayer;
641
- }
642
- removePolygonLayer(layerName) {
643
- new MapTools(this.map).removeLayer(layerName);
644
- this[layerName] = null;
645
- }
646
- }