my-openlayer 2.4.12 → 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 (171) hide show
  1. package/CHANGELOG.md +251 -251
  2. package/LICENSE +21 -21
  3. package/MyOl.d.ts +9 -9
  4. package/MyOl.js +17 -14
  5. package/README.md +174 -148
  6. package/core/line/Line.d.ts +40 -0
  7. package/core/line/Line.js +144 -0
  8. package/core/line/LineFeatureFactory.d.ts +17 -0
  9. package/core/line/LineFeatureFactory.js +75 -0
  10. package/core/line/LineFlowAnimator.d.ts +53 -0
  11. package/core/line/LineFlowAnimator.js +297 -0
  12. package/core/line/LineStyleFactory.d.ts +43 -0
  13. package/core/line/LineStyleFactory.js +135 -0
  14. package/core/{RiverLayerManager.d.ts → line/RiverLayerManager.d.ts} +2 -2
  15. package/core/{RiverLayerManager.js → line/RiverLayerManager.js} +3 -5
  16. package/core/line/index.d.ts +6 -0
  17. package/core/line/index.js +5 -0
  18. package/core/{ConfigManager.d.ts → map/ConfigManager.d.ts} +25 -1
  19. package/core/{ConfigManager.js → map/ConfigManager.js} +22 -1
  20. package/core/{EventManager.d.ts → map/EventManager.d.ts} +1 -1
  21. package/core/{EventManager.js → map/EventManager.js} +2 -2
  22. package/core/{MapBaseLayers.d.ts → map/MapBaseLayers.d.ts} +1 -1
  23. package/core/{MapBaseLayers.js → map/MapBaseLayers.js} +3 -3
  24. package/core/{MapTools.d.ts → map/MapTools.d.ts} +5 -2
  25. package/core/{MapTools.js → map/MapTools.js} +11 -5
  26. package/core/{MeasureHandler.d.ts → map/MeasureHandler.d.ts} +1 -1
  27. package/core/{MeasureHandler.js → map/MeasureHandler.js} +41 -41
  28. package/core/map/index.d.ts +5 -0
  29. package/core/map/index.js +5 -0
  30. package/core/{Point.d.ts → point/Point.d.ts} +6 -14
  31. package/core/point/Point.js +272 -0
  32. package/core/point/PointClusterLayer.d.ts +10 -0
  33. package/core/point/PointClusterLayer.js +52 -0
  34. package/core/point/PointOverlay.d.ts +13 -0
  35. package/core/point/PointOverlay.js +57 -0
  36. package/core/point/PointPulseLayer.d.ts +13 -0
  37. package/core/point/PointPulseLayer.js +207 -0
  38. package/core/point/index.d.ts +4 -0
  39. package/core/point/index.js +4 -0
  40. package/core/{Polygon.d.ts → polygon/Polygon.d.ts} +4 -50
  41. package/core/polygon/Polygon.js +248 -0
  42. package/core/polygon/PolygonHeatmapLayer.d.ts +11 -0
  43. package/core/polygon/PolygonHeatmapLayer.js +40 -0
  44. package/core/polygon/PolygonImageLayer.d.ts +9 -0
  45. package/core/polygon/PolygonImageLayer.js +61 -0
  46. package/core/polygon/PolygonMaskLayer.d.ts +20 -0
  47. package/core/polygon/PolygonMaskLayer.js +107 -0
  48. package/core/polygon/PolygonStyleFactory.d.ts +12 -0
  49. package/core/polygon/PolygonStyleFactory.js +100 -0
  50. package/core/polygon/index.d.ts +5 -0
  51. package/core/polygon/index.js +5 -0
  52. package/core/{SelectHandler.d.ts → select/SelectHandler.d.ts} +2 -3
  53. package/core/{SelectHandler.js → select/SelectHandler.js} +4 -4
  54. package/core/select/index.d.ts +1 -0
  55. package/core/select/index.js +1 -0
  56. package/core/{VueTemplatePoint.d.ts → vue-template-point/VueTemplatePoint.d.ts} +1 -1
  57. package/core/{VueTemplatePoint.js → vue-template-point/VueTemplatePoint.js} +4 -4
  58. package/core/vue-template-point/index.d.ts +1 -0
  59. package/core/vue-template-point/index.js +1 -0
  60. package/docs/.vitepress/config.mts +57 -57
  61. package/docs/ConfigManager.md +71 -71
  62. package/docs/ErrorHandler.md +106 -106
  63. package/docs/EventManager.md +142 -142
  64. package/docs/Line.md +215 -187
  65. package/docs/MapBaseLayers.md +198 -198
  66. package/docs/MapTools.md +172 -172
  67. package/docs/MeasureHandler.md +87 -87
  68. package/docs/MyOl.md +247 -247
  69. package/docs/Point.md +136 -136
  70. package/docs/Polygon.md +241 -241
  71. package/docs/RiverLayerManager.md +187 -187
  72. package/docs/SelectHandler.md +147 -147
  73. package/docs/ValidationUtils.md +83 -83
  74. package/docs/VueTemplatePoint.md +214 -214
  75. package/docs/index.md +73 -73
  76. package/index.d.ts +10 -15
  77. package/index.js +7 -13
  78. package/package.json +11 -1
  79. package/types/base.d.ts +47 -0
  80. package/types/base.js +1 -0
  81. package/types/common.d.ts +59 -0
  82. package/types/common.js +1 -0
  83. package/types/index.d.ts +9 -0
  84. package/types/index.js +1 -0
  85. package/types/line.d.ts +41 -0
  86. package/types/line.js +1 -0
  87. package/types/map.d.ts +77 -0
  88. package/types/map.js +1 -0
  89. package/types/point.d.ts +54 -0
  90. package/types/point.js +1 -0
  91. package/types/polygon.d.ts +8 -0
  92. package/types/polygon.js +1 -0
  93. package/types/select.d.ts +25 -0
  94. package/types/select.js +1 -0
  95. package/types/vue-template-point.d.ts +54 -0
  96. package/{types.js → types/vue-template-point.js} +0 -3
  97. package/utils/ProjectionUtils.d.ts +28 -0
  98. package/utils/ProjectionUtils.js +34 -0
  99. package/utils/ValidationUtils.d.ts +33 -86
  100. package/utils/ValidationUtils.js +60 -165
  101. package/core/Line.d.ts +0 -49
  102. package/core/Line.js +0 -114
  103. package/core/Point.js +0 -560
  104. package/core/Polygon.js +0 -646
  105. package/docs/.vitepress/dist/404.html +0 -22
  106. package/docs/.vitepress/dist/ConfigManager.html +0 -46
  107. package/docs/.vitepress/dist/ErrorHandler.html +0 -52
  108. package/docs/.vitepress/dist/EventManager.html +0 -58
  109. package/docs/.vitepress/dist/Line.html +0 -92
  110. package/docs/.vitepress/dist/MapBaseLayers.html +0 -52
  111. package/docs/.vitepress/dist/MapTools.html +0 -81
  112. package/docs/.vitepress/dist/MeasureHandler.html +0 -32
  113. package/docs/.vitepress/dist/MyOl.html +0 -62
  114. package/docs/.vitepress/dist/Point.html +0 -81
  115. package/docs/.vitepress/dist/Polygon.html +0 -102
  116. package/docs/.vitepress/dist/RiverLayerManager.html +0 -66
  117. package/docs/.vitepress/dist/SelectHandler.html +0 -46
  118. package/docs/.vitepress/dist/ValidationUtils.html +0 -47
  119. package/docs/.vitepress/dist/VueTemplatePoint.html +0 -112
  120. package/docs/.vitepress/dist/assets/ConfigManager.md.BOMdGTaa.js +0 -22
  121. package/docs/.vitepress/dist/assets/ConfigManager.md.BOMdGTaa.lean.js +0 -1
  122. package/docs/.vitepress/dist/assets/ErrorHandler.md.yUiuJ9w9.js +0 -28
  123. package/docs/.vitepress/dist/assets/ErrorHandler.md.yUiuJ9w9.lean.js +0 -1
  124. package/docs/.vitepress/dist/assets/EventManager.md.BhCUVy1f.js +0 -34
  125. package/docs/.vitepress/dist/assets/EventManager.md.BhCUVy1f.lean.js +0 -1
  126. package/docs/.vitepress/dist/assets/Line.md.BAQOzmSt.js +0 -68
  127. package/docs/.vitepress/dist/assets/Line.md.BAQOzmSt.lean.js +0 -1
  128. package/docs/.vitepress/dist/assets/MapBaseLayers.md.Bw0L_m0b.js +0 -28
  129. package/docs/.vitepress/dist/assets/MapBaseLayers.md.Bw0L_m0b.lean.js +0 -1
  130. package/docs/.vitepress/dist/assets/MapTools.md.DaYgiDPe.js +0 -57
  131. package/docs/.vitepress/dist/assets/MapTools.md.DaYgiDPe.lean.js +0 -1
  132. package/docs/.vitepress/dist/assets/MeasureHandler.md.7Sf4ymRv.js +0 -8
  133. package/docs/.vitepress/dist/assets/MeasureHandler.md.7Sf4ymRv.lean.js +0 -1
  134. package/docs/.vitepress/dist/assets/MyOl.md.D-14Gzjy.js +0 -38
  135. package/docs/.vitepress/dist/assets/MyOl.md.D-14Gzjy.lean.js +0 -1
  136. package/docs/.vitepress/dist/assets/Point.md.Bi9juuuv.js +0 -57
  137. package/docs/.vitepress/dist/assets/Point.md.Bi9juuuv.lean.js +0 -1
  138. package/docs/.vitepress/dist/assets/Polygon.md.-JIqEvzD.js +0 -78
  139. package/docs/.vitepress/dist/assets/Polygon.md.-JIqEvzD.lean.js +0 -1
  140. package/docs/.vitepress/dist/assets/RiverLayerManager.md.CfUu2RxH.js +0 -42
  141. package/docs/.vitepress/dist/assets/RiverLayerManager.md.CfUu2RxH.lean.js +0 -1
  142. package/docs/.vitepress/dist/assets/SelectHandler.md.COR4ez_p.js +0 -22
  143. package/docs/.vitepress/dist/assets/SelectHandler.md.COR4ez_p.lean.js +0 -1
  144. package/docs/.vitepress/dist/assets/ValidationUtils.md.ReTVWa73.js +0 -23
  145. package/docs/.vitepress/dist/assets/ValidationUtils.md.ReTVWa73.lean.js +0 -1
  146. package/docs/.vitepress/dist/assets/VueTemplatePoint.md.CtxSb5Pm.js +0 -88
  147. package/docs/.vitepress/dist/assets/VueTemplatePoint.md.CtxSb5Pm.lean.js +0 -1
  148. package/docs/.vitepress/dist/assets/app.YvjVuxaB.js +0 -1
  149. package/docs/.vitepress/dist/assets/chunks/framework.C_W0ODpn.js +0 -18
  150. package/docs/.vitepress/dist/assets/chunks/theme.Bf87fILP.js +0 -1
  151. package/docs/.vitepress/dist/assets/index.md.BJz6tHSr.js +0 -26
  152. package/docs/.vitepress/dist/assets/index.md.BJz6tHSr.lean.js +0 -1
  153. package/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  154. package/docs/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  155. package/docs/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  156. package/docs/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  157. package/docs/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  158. package/docs/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  159. package/docs/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  160. package/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  161. package/docs/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  162. package/docs/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  163. package/docs/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  164. package/docs/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  165. package/docs/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  166. package/docs/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  167. package/docs/.vitepress/dist/assets/style.C2pAQzDq.css +0 -1
  168. package/docs/.vitepress/dist/hashmap.json +0 -1
  169. package/docs/.vitepress/dist/index.html +0 -50
  170. package/docs/.vitepress/dist/vp-icons.css +0 -1
  171. package/types.d.ts +0 -431
@@ -0,0 +1,207 @@
1
+ import Feature from "ol/Feature";
2
+ import { Point as OlPoint } from "ol/geom";
3
+ import VectorLayer from "ol/layer/Vector";
4
+ import VectorSource from "ol/source/Vector";
5
+ import { Circle as CircleStyle, Fill, Icon, Stroke, Style, Text } from "ol/style";
6
+ import ProjectionUtils from "../../utils/ProjectionUtils";
7
+ import ValidationUtils from "../../utils/ValidationUtils";
8
+ import { ConfigManager } from "../map";
9
+ /**
10
+ * 高性能闪烁点图层构建器。
11
+ */
12
+ export default class PointPulseLayer {
13
+ static createTextStyle(options, text) {
14
+ const defaultTextOptions = ConfigManager.DEFAULT_POINT_TEXT_OPTIONS;
15
+ return new Text({
16
+ text,
17
+ font: options.textFont || defaultTextOptions.textFont,
18
+ fill: new Fill({ color: options.textFillColor || defaultTextOptions.textFillColor }),
19
+ stroke: new Stroke({
20
+ color: options.textStrokeColor || defaultTextOptions.textStrokeColor,
21
+ width: options.textStrokeWidth || defaultTextOptions.textStrokeWidth
22
+ }),
23
+ offsetY: options.textOffsetY || defaultTextOptions.textOffsetY
24
+ });
25
+ }
26
+ static withOpacity(color, opacity) {
27
+ const safeOpacity = Math.max(0, Math.min(1, opacity));
28
+ const rgbaMatch = color.match(/^rgba?\(([^)]+)\)$/i);
29
+ if (rgbaMatch) {
30
+ const parts = rgbaMatch[1].split(',').map(part => part.trim());
31
+ if (parts.length >= 3) {
32
+ const alpha = parts.length >= 4 ? Number(parts[3]) : 1;
33
+ const nextAlpha = Number.isFinite(alpha) ? alpha * safeOpacity : safeOpacity;
34
+ return `rgba(${parts[0]}, ${parts[1]}, ${parts[2]}, ${nextAlpha})`;
35
+ }
36
+ }
37
+ if (/^#[0-9a-f]{6}$/i.test(color)) {
38
+ const red = parseInt(color.slice(1, 3), 16);
39
+ const green = parseInt(color.slice(3, 5), 16);
40
+ const blue = parseInt(color.slice(5, 7), 16);
41
+ return `rgba(${red}, ${green}, ${blue}, ${safeOpacity})`;
42
+ }
43
+ return color;
44
+ }
45
+ static createFeatures(pointData, options) {
46
+ const pointFeatureList = [];
47
+ pointData.forEach(item => {
48
+ if (!ValidationUtils.validateCoordinates(item)) {
49
+ return;
50
+ }
51
+ pointFeatureList.push(new Feature({
52
+ rawData: item,
53
+ type: options.layerName,
54
+ layerName: options.layerName,
55
+ geometry: new OlPoint(ProjectionUtils.transformCoordinate([item.lgtd, item.lttd], options))
56
+ }));
57
+ });
58
+ return pointFeatureList;
59
+ }
60
+ static create(map, pointData, options) {
61
+ const pulseOptions = {
62
+ enabled: options.pulse?.enabled ?? true,
63
+ duration: options.pulse?.duration ?? 2400,
64
+ radius: options.pulse?.radius ?? [8, 26],
65
+ colorMap: options.pulse?.colorMap ?? {
66
+ 0: 'rgba(255, 48, 54, 0.45)',
67
+ 1: 'rgba(255, 136, 0, 0.45)',
68
+ 2: 'rgba(253, 216, 46, 0.38)',
69
+ 3: 'rgba(6, 183, 253, 0.3)'
70
+ },
71
+ strokeColorMap: options.pulse?.strokeColorMap,
72
+ strokeWidth: options.pulse?.strokeWidth ?? 0,
73
+ frameCount: Math.max(1, options.pulse?.frameCount ?? 24)
74
+ };
75
+ const levelKey = options.levelKey ?? 'lev';
76
+ const pulseStyleCache = new globalThis.Map();
77
+ const staticStyleCache = new globalThis.Map();
78
+ let frameIndex = 0;
79
+ let renderedFrameIndex = -1;
80
+ let rafId = null;
81
+ let running = false;
82
+ const source = new VectorSource({
83
+ features: PointPulseLayer.createFeatures(pointData, options)
84
+ });
85
+ const createStyles = (feature) => {
86
+ const rawData = feature.get('rawData');
87
+ const level = rawData?.[levelKey] ?? 'default';
88
+ const progress = frameIndex / Math.max(1, pulseOptions.frameCount - 1);
89
+ const [minRadius, maxRadius] = pulseOptions.radius;
90
+ const radius = minRadius + (maxRadius - minRadius) * progress;
91
+ const opacity = 1 - progress;
92
+ const fillColor = pulseOptions.colorMap[level] ?? pulseOptions.colorMap.default ?? 'rgba(6, 183, 253, 0.32)';
93
+ const strokeColor = pulseOptions.strokeColorMap?.[level] ?? pulseOptions.strokeColorMap?.default;
94
+ const styles = [];
95
+ if (pulseOptions.enabled) {
96
+ const pulseCacheKey = `${level}_${frameIndex}`;
97
+ let pulseStyle = pulseStyleCache.get(pulseCacheKey);
98
+ if (!pulseStyle) {
99
+ pulseStyle = new Style({
100
+ zIndex: 0,
101
+ image: new CircleStyle({
102
+ radius,
103
+ fill: new Fill({ color: PointPulseLayer.withOpacity(fillColor, opacity) }),
104
+ stroke: strokeColor && pulseOptions.strokeWidth > 0
105
+ ? new Stroke({ color: PointPulseLayer.withOpacity(strokeColor, opacity), width: pulseOptions.strokeWidth })
106
+ : undefined
107
+ })
108
+ });
109
+ pulseStyleCache.set(pulseCacheKey, pulseStyle);
110
+ }
111
+ styles.push(pulseStyle);
112
+ }
113
+ const text = options.textVisible && options.textKey && rawData ? rawData[options.textKey] ?? '' : '';
114
+ const staticCacheKey = [
115
+ options.img ?? options.icon?.src ?? '',
116
+ options.scale ?? options.icon?.scale ?? ConfigManager.DEFAULT_POINT_ICON_SCALE,
117
+ options.iconColor ?? options.icon?.color ?? '',
118
+ text
119
+ ].join('|');
120
+ let pointStyle = staticStyleCache.get(staticCacheKey);
121
+ if (pointStyle) {
122
+ styles.push(pointStyle);
123
+ return styles;
124
+ }
125
+ const pointStyleOptions = {};
126
+ const iconSrc = options.img ?? options.icon?.src;
127
+ if (iconSrc) {
128
+ pointStyleOptions.image = new Icon({
129
+ src: iconSrc,
130
+ scale: options.scale ?? options.icon?.scale ?? ConfigManager.DEFAULT_POINT_ICON_SCALE,
131
+ color: options.iconColor ?? options.icon?.color
132
+ });
133
+ }
134
+ else if (options.icon) {
135
+ pointStyleOptions.image = new CircleStyle({
136
+ radius: options.icon.radius ?? 5,
137
+ fill: new Fill({ color: options.icon.fillColor ?? '#06b7fd' }),
138
+ stroke: new Stroke({
139
+ color: options.icon.strokeColor ?? '#ffffff',
140
+ width: options.icon.strokeWidth ?? 2
141
+ })
142
+ });
143
+ }
144
+ if (text) {
145
+ pointStyleOptions.text = PointPulseLayer.createTextStyle(options, text);
146
+ }
147
+ if (pointStyleOptions.image || pointStyleOptions.text) {
148
+ pointStyle = new Style(pointStyleOptions);
149
+ pointStyle.setZIndex(1);
150
+ staticStyleCache.set(staticCacheKey, pointStyle);
151
+ styles.push(pointStyle);
152
+ }
153
+ return styles;
154
+ };
155
+ const layer = new VectorLayer({
156
+ layerName: options.layerName,
157
+ source,
158
+ style: createStyles,
159
+ zIndex: options.zIndex || ConfigManager.DEFAULT_POINT_OPTIONS.zIndex,
160
+ });
161
+ layer.setVisible(options.visible === undefined ? true : options.visible);
162
+ map.addLayer(layer);
163
+ const tick = () => {
164
+ if (!running)
165
+ return;
166
+ const duration = Math.max(1, pulseOptions.duration);
167
+ const now = typeof performance !== 'undefined' ? performance.now() : Date.now();
168
+ const nextFrameIndex = Math.floor(((now % duration) / duration) * pulseOptions.frameCount);
169
+ if (nextFrameIndex !== renderedFrameIndex) {
170
+ frameIndex = nextFrameIndex;
171
+ renderedFrameIndex = nextFrameIndex;
172
+ layer.changed();
173
+ }
174
+ rafId = requestAnimationFrame(tick);
175
+ };
176
+ const stop = () => {
177
+ running = false;
178
+ if (rafId !== null) {
179
+ cancelAnimationFrame(rafId);
180
+ rafId = null;
181
+ }
182
+ };
183
+ const start = () => {
184
+ if (running || !pulseOptions.enabled)
185
+ return;
186
+ running = true;
187
+ tick();
188
+ };
189
+ start();
190
+ return {
191
+ layer,
192
+ source,
193
+ start,
194
+ stop,
195
+ setVisible: (visible) => layer.setVisible(visible),
196
+ updateData: (nextData) => {
197
+ source.clear();
198
+ source.addFeatures(PointPulseLayer.createFeatures(nextData, options));
199
+ },
200
+ remove: () => {
201
+ stop();
202
+ source.clear();
203
+ map.removeLayer(layer);
204
+ }
205
+ };
206
+ }
207
+ }
@@ -0,0 +1,4 @@
1
+ export { default as Point } from './Point';
2
+ export { default as PointPulseLayer } from './PointPulseLayer';
3
+ export { default as PointClusterLayer } from './PointClusterLayer';
4
+ export { default as PointOverlay } from './PointOverlay';
@@ -0,0 +1,4 @@
1
+ export { default as Point } from './Point';
2
+ export { default as PointPulseLayer } from './PointPulseLayer';
3
+ export { default as PointClusterLayer } from './PointClusterLayer';
4
+ export { default as PointOverlay } from './PointOverlay';
@@ -1,10 +1,9 @@
1
1
  import Map from "ol/Map";
2
2
  import VectorLayer from "ol/layer/Vector";
3
3
  import VectorSource from "ol/source/Vector";
4
- import { Image as ImageLayer, Heatmap } from "ol/layer";
5
- import { Geometry } from "ol/geom";
4
+ import { Image as ImageLayer } from "ol/layer";
6
5
  import Feature from "ol/Feature";
7
- import { PolygonOptions, MapJSONData, PointData, HeatMapOptions, ImageLayerData, MaskLayerOptions, FeatureColorUpdateOptions } from '../types';
6
+ import { PolygonOptions, MapJSONData, PointData, HeatMapOptions, ImageLayerData, MaskLayerOptions, FeatureColorUpdateOptions } from '../../types';
8
7
  /**
9
8
  * Polygon 类用于处理地图上的面要素操作
10
9
  * 包括添加多边形、边框、图片图层、热力图等功能
@@ -49,19 +48,6 @@ export default class Polygon {
49
48
  * @throws 当数据格式无效时抛出错误
50
49
  */
51
50
  addPolygonByUrl(url: string, options?: PolygonOptions): VectorLayer<VectorSource>;
52
- /**
53
- * 创建样式或样式函数
54
- * @param options 配置选项
55
- * @returns 样式或样式函数
56
- */
57
- private createStyle;
58
- /**
59
- * 获取要素文本
60
- * @param feature 要素对象
61
- * @param options 配置选项
62
- * @returns 文本内容
63
- */
64
- private getFeatureText;
65
51
  /**
66
52
  * 适应图层视图
67
53
  * @param layer 图层对象
@@ -77,13 +63,6 @@ export default class Polygon {
77
63
  updateFeatureColor(layerName: string, colorObj?: {
78
64
  [propName: string]: string;
79
65
  }, options?: FeatureColorUpdateOptions): void;
80
- /**
81
- * 更新单个要素的颜色
82
- * @param feature 要素对象
83
- * @param colorObj 颜色映射对象
84
- * @param options 配置选项
85
- */
86
- private updateSingleFeatureColor;
87
66
  /**
88
67
  * 设置外围蒙版图层
89
68
  *
@@ -99,7 +78,7 @@ export default class Polygon {
99
78
  strokeWidth?: number;
100
79
  strokeColor?: string;
101
80
  zIndex?: number;
102
- }): VectorLayer<VectorSource<Feature<Geometry>>, Feature<Geometry>>;
81
+ }): VectorLayer<VectorSource<Feature<import("ol/geom").Geometry>>, Feature<import("ol/geom").Geometry>>;
103
82
  /**
104
83
  * 添加图片图层
105
84
  * @param imageData 图片数据,包含url和extent
@@ -108,37 +87,12 @@ export default class Polygon {
108
87
  * @throws 当数据格式无效时抛出错误
109
88
  */
110
89
  addImageLayer(imageData: ImageLayerData, options?: PolygonOptions): ImageLayer<any>;
111
- /**
112
- * 尝试更新现有图层
113
- * @private
114
- */
115
- private tryUpdateExistingImageLayer;
116
- /**
117
- * 创建新的图像图层
118
- * @private
119
- */
120
- private createNewImageLayer;
121
- /**
122
- * 更新图层属性
123
- * @private
124
- */
125
- private updateImageLayerProperties;
126
- /**
127
- * 配置图层基本属性
128
- * @private
129
- */
130
- private configureImageLayer;
131
- /**
132
- * 添加图层到地图并应用裁剪
133
- * @private
134
- */
135
- private addImageLayerToMap;
136
90
  /**
137
91
  * 添加热力图图层
138
92
  * @param pointData 点数据数组
139
93
  * @param options 热力图配置
140
94
  */
141
- addHeatmap(pointData: PointData[], options?: HeatMapOptions): Heatmap<Feature<Geometry>, VectorSource<Feature<Geometry>>>;
95
+ addHeatmap(pointData: PointData[], options?: HeatMapOptions): import("ol/layer").Heatmap<Feature<import("ol/geom").Geometry>, VectorSource<Feature<import("ol/geom").Geometry>>>;
142
96
  /**
143
97
  * 添加遮罩图层
144
98
  * @param data GeoJSON格式的遮罩数据
@@ -0,0 +1,248 @@
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 { ErrorHandler } from '../../utils/ErrorHandler';
6
+ import ProjectionUtils from '../../utils/ProjectionUtils';
7
+ import ValidationUtils from '../../utils/ValidationUtils';
8
+ import { ConfigManager, MapTools } from "../map";
9
+ import PolygonHeatmapLayer from './PolygonHeatmapLayer';
10
+ import PolygonImageLayer from './PolygonImageLayer';
11
+ import PolygonMaskLayer from './PolygonMaskLayer';
12
+ import PolygonStyleFactory from './PolygonStyleFactory';
13
+ /**
14
+ * Polygon 类用于处理地图上的面要素操作
15
+ * 包括添加多边形、边框、图片图层、热力图等功能
16
+ */
17
+ export default class Polygon {
18
+ /**
19
+ * 构造函数
20
+ * @param map OpenLayers 地图实例
21
+ */
22
+ constructor(map) {
23
+ if (!map) {
24
+ throw new Error('Map instance is required');
25
+ }
26
+ this.map = map;
27
+ }
28
+ /**
29
+ * 添加地图边框图层
30
+ * @param data 图层数据,必须是有效的 GeoJSON 格式
31
+ * @param options 图层配置选项
32
+ * @returns 创建的图层实例
33
+ * @throws 当数据格式无效时抛出错误
34
+ */
35
+ addBorderPolygon(data, options) {
36
+ ValidationUtils.validateGeoJSONData(data);
37
+ const mergedOptions = {
38
+ fillColor: 'rgba(255, 255, 255, 0)',
39
+ ...options
40
+ };
41
+ const layer = this.addPolygon(data, mergedOptions);
42
+ if (mergedOptions.mask) {
43
+ this.setOutLayer(data);
44
+ }
45
+ return layer;
46
+ }
47
+ /**
48
+ * 从URL添加地图边框图层
49
+ * @param url 数据URL
50
+ * @param options 图层配置选项
51
+ * @returns 创建的图层实例
52
+ * @throws 当数据格式无效时抛出错误
53
+ */
54
+ addBorderPolygonByUrl(url, options) {
55
+ const mergedOptions = {
56
+ layerName: 'border',
57
+ fillColor: 'rgba(255, 255, 255, 0)',
58
+ ...options
59
+ };
60
+ const layer = this.addPolygonByUrl(url, mergedOptions);
61
+ return layer;
62
+ }
63
+ /**
64
+ * 添加多边形图层
65
+ * @param dataJSON GeoJSON 数据
66
+ * @param options 图层配置选项
67
+ * @returns 创建的矢量图层
68
+ * @throws 当数据格式无效时抛出错误
69
+ */
70
+ addPolygon(dataJSON, options) {
71
+ ValidationUtils.validateGeoJSONData(dataJSON);
72
+ const mergedOptions = {
73
+ ...ConfigManager.DEFAULT_POLYGON_OPTIONS,
74
+ ...options
75
+ };
76
+ // 如果指定了图层名称,先移除同名图层
77
+ if (mergedOptions.layerName) {
78
+ new MapTools(this.map).removeLayer(mergedOptions.layerName);
79
+ }
80
+ const format = new GeoJSON();
81
+ // 优化:在解析 Feature 时直接注入 layerName,利用解析过程的遍历,避免解析后的二次循环
82
+ if (mergedOptions.layerName) {
83
+ const originalReadFeatureFromObject = format.readFeatureFromObject;
84
+ format.readFeatureFromObject = function (object, options) {
85
+ const feature = originalReadFeatureFromObject.call(this, object, options);
86
+ feature.set('layerName', mergedOptions.layerName, true); // true 表示静默设置,不触发事件
87
+ return feature;
88
+ };
89
+ }
90
+ let features;
91
+ try {
92
+ features = format.readFeatures(dataJSON, ProjectionUtils.getGeoJSONReadOptions(mergedOptions));
93
+ }
94
+ catch (error) {
95
+ throw new Error(`Failed to parse GeoJSON data: ${error}`);
96
+ }
97
+ const layer = new VectorLayer({
98
+ properties: {
99
+ name: mergedOptions.layerName,
100
+ layerName: mergedOptions.layerName
101
+ },
102
+ source: new VectorSource({ features }),
103
+ style: PolygonStyleFactory.createStyle(mergedOptions),
104
+ zIndex: mergedOptions.zIndex
105
+ });
106
+ layer.setVisible(mergedOptions.visible);
107
+ this.map.addLayer(layer);
108
+ // 如果需要适应视图
109
+ if (mergedOptions.fitView) {
110
+ this.fitViewToLayer(layer);
111
+ }
112
+ return layer;
113
+ }
114
+ /**
115
+ * 从URL添加多边形图层
116
+ * @param url 数据URL
117
+ * @param options 图层配置选项
118
+ * @returns 创建的矢量图层
119
+ * @throws 当数据格式无效时抛出错误
120
+ */
121
+ addPolygonByUrl(url, options) {
122
+ const mergedOptions = {
123
+ ...ConfigManager.DEFAULT_POLYGON_OPTIONS,
124
+ ...options
125
+ };
126
+ // 如果指定了图层名称,先移除同名图层
127
+ if (mergedOptions.layerName) {
128
+ new MapTools(this.map).removeLayer(mergedOptions.layerName);
129
+ }
130
+ const format = new GeoJSON(ProjectionUtils.getGeoJSONReadOptions(mergedOptions));
131
+ // 优化:在解析 Feature 时直接注入 layerName,利用解析过程的遍历,避免解析后的二次循环
132
+ if (mergedOptions.layerName) {
133
+ const originalReadFeatureFromObject = format.readFeatureFromObject;
134
+ format.readFeatureFromObject = function (object, options) {
135
+ const feature = originalReadFeatureFromObject.call(this, object, options);
136
+ feature.set('layerName', mergedOptions.layerName, true); // true 表示静默设置,不触发事件
137
+ return feature;
138
+ };
139
+ }
140
+ const source = new VectorSource({
141
+ url,
142
+ format
143
+ });
144
+ const layer = new VectorLayer({
145
+ properties: {
146
+ name: mergedOptions.layerName,
147
+ layerName: mergedOptions.layerName
148
+ },
149
+ source,
150
+ style: PolygonStyleFactory.createStyle(mergedOptions),
151
+ zIndex: mergedOptions.zIndex
152
+ });
153
+ layer.setVisible(mergedOptions.visible);
154
+ this.map.addLayer(layer);
155
+ // 如果需要适应视图
156
+ if (mergedOptions.fitView) {
157
+ source.once('featuresloadend', () => {
158
+ this.fitViewToLayer(layer);
159
+ });
160
+ }
161
+ return layer;
162
+ }
163
+ /**
164
+ * 适应图层视图
165
+ * @param layer 图层对象
166
+ */
167
+ fitViewToLayer(layer) {
168
+ const extent = layer.getSource()?.getExtent();
169
+ if (extent) {
170
+ this.map.getView().fit(extent, { duration: 500 });
171
+ }
172
+ }
173
+ /**
174
+ * 根据数据数组更新某个面颜色
175
+ * @param layerName 图层名称
176
+ * @param colorObj 颜色映射对象,键为要素属性值,值为颜色字符串
177
+ * @param options 配置项
178
+ * @throws 当图层不存在时抛出错误
179
+ */
180
+ updateFeatureColor(layerName, colorObj, options) {
181
+ ValidationUtils.validateLayerName(layerName);
182
+ const layers = MapTools.getLayerByLayerName(this.map, layerName);
183
+ if (layers.length === 0) {
184
+ throw new Error(`Layer with name '${layerName}' not found`);
185
+ }
186
+ const layer = layers[0];
187
+ if (!(layer instanceof VectorLayer)) {
188
+ throw new Error(`Layer '${layerName}' is not a vector layer`);
189
+ }
190
+ const mergedOptions = {
191
+ textFont: '14px Calibri,sans-serif',
192
+ textFillColor: '#FFF',
193
+ textStrokeWidth: 2,
194
+ ...options
195
+ };
196
+ const features = layer.getSource()?.getFeatures();
197
+ if (!features) {
198
+ ErrorHandler.getInstance().warn(`No features found in layer '${layerName}'`);
199
+ return;
200
+ }
201
+ features.forEach((feature) => {
202
+ PolygonStyleFactory.updateSingleFeatureColor(feature, colorObj, mergedOptions);
203
+ });
204
+ }
205
+ /**
206
+ * 设置外围蒙版图层
207
+ *
208
+ * 详细文档参考 https_blog.csdn.net/?url=https%3A%2F%2Fblog.csdn.net%2Fu012413551%2Farticle%2Fdetails%2F122739501
209
+ *
210
+ * @param data
211
+ * @param options
212
+ */
213
+ setOutLayer(data, options) {
214
+ return PolygonMaskLayer.setOutLayer(this.map, data, options);
215
+ }
216
+ /**
217
+ * 添加图片图层
218
+ * @param imageData 图片数据,包含url和extent
219
+ * @param options 配置项
220
+ * @returns 创建的图片图层
221
+ * @throws 当数据格式无效时抛出错误
222
+ */
223
+ addImageLayer(imageData, options) {
224
+ return PolygonImageLayer.addImageLayer(this.map, imageData, options);
225
+ }
226
+ /**
227
+ * 添加热力图图层
228
+ * @param pointData 点数据数组
229
+ * @param options 热力图配置
230
+ */
231
+ addHeatmap(pointData, options) {
232
+ return PolygonHeatmapLayer.addHeatmap(this.map, pointData, options);
233
+ }
234
+ /**
235
+ * 添加遮罩图层
236
+ * @param data GeoJSON格式的遮罩数据
237
+ * @param options 配置项
238
+ * @returns 创建的遮罩图层
239
+ * @throws 当数据格式无效时抛出错误
240
+ */
241
+ addMaskLayer(data, options) {
242
+ return PolygonMaskLayer.addMaskLayer(this.map, data, options);
243
+ }
244
+ removePolygonLayer(layerName) {
245
+ new MapTools(this.map).removeLayer(layerName);
246
+ this[layerName] = null;
247
+ }
248
+ }
@@ -0,0 +1,11 @@
1
+ import Feature from "ol/Feature";
2
+ import Map from "ol/Map";
3
+ import { Heatmap } from "ol/layer";
4
+ import VectorSource from "ol/source/Vector";
5
+ import type { HeatMapOptions, PointData } from "../../types";
6
+ /**
7
+ * 面热力图辅助类。
8
+ */
9
+ export default class PolygonHeatmapLayer {
10
+ static addHeatmap(map: Map, pointData: PointData[], options?: HeatMapOptions): Heatmap<Feature<import("ol/geom").Geometry>, VectorSource<Feature<import("ol/geom").Geometry>>>;
11
+ }
@@ -0,0 +1,40 @@
1
+ import Feature from "ol/Feature";
2
+ import { Point } from "ol/geom";
3
+ import { Heatmap } from "ol/layer";
4
+ import VectorSource from "ol/source/Vector";
5
+ import { ConfigManager, MapTools } from "../map";
6
+ /**
7
+ * 面热力图辅助类。
8
+ */
9
+ export default class PolygonHeatmapLayer {
10
+ static addHeatmap(map, pointData, options) {
11
+ if (options?.layerName) {
12
+ new MapTools(map).removeLayer(options.layerName);
13
+ }
14
+ const mergedOptions = {
15
+ ...ConfigManager.DEFAULT_HEATMAP_OPTIONS,
16
+ ...options
17
+ };
18
+ const heatmapLayer = new Heatmap({
19
+ source: new VectorSource(),
20
+ weight: (feature) => feature.get('weight'),
21
+ blur: mergedOptions.blur ?? ConfigManager.DEFAULT_HEATMAP_OPTIONS.blur,
22
+ radius: mergedOptions.radius ?? ConfigManager.DEFAULT_HEATMAP_OPTIONS.radius,
23
+ zIndex: mergedOptions.zIndex ?? ConfigManager.DEFAULT_HEATMAP_OPTIONS.zIndex,
24
+ opacity: mergedOptions.opacity ?? ConfigManager.DEFAULT_HEATMAP_OPTIONS.opacity
25
+ });
26
+ if (mergedOptions.layerName) {
27
+ heatmapLayer.set('layerName', mergedOptions.layerName);
28
+ }
29
+ map.addLayer(heatmapLayer);
30
+ const valueKey = mergedOptions.valueKey || ConfigManager.DEFAULT_HEATMAP_VALUE_KEY;
31
+ const max = Math.max(...pointData.map(item => item[valueKey]));
32
+ pointData.forEach(item => {
33
+ heatmapLayer.getSource().addFeature(new Feature({
34
+ geometry: new Point([item.lgtd, item.lttd]),
35
+ weight: item[valueKey] / max
36
+ }));
37
+ });
38
+ return heatmapLayer;
39
+ }
40
+ }
@@ -0,0 +1,9 @@
1
+ import Map from "ol/Map";
2
+ import { Image as ImageLayer } from "ol/layer";
3
+ import type { ImageLayerData, PolygonOptions } from "../../types";
4
+ /**
5
+ * 面图片图层辅助类。
6
+ */
7
+ export default class PolygonImageLayer {
8
+ static addImageLayer(map: Map, imageData: ImageLayerData, options?: PolygonOptions): ImageLayer<any>;
9
+ }
@@ -0,0 +1,61 @@
1
+ import ImageStatic from "ol/source/ImageStatic";
2
+ import { Image as ImageLayer } from "ol/layer";
3
+ import ValidationUtils from "../../utils/ValidationUtils";
4
+ import { ConfigManager, MapTools } from "../map";
5
+ /**
6
+ * 面图片图层辅助类。
7
+ */
8
+ export default class PolygonImageLayer {
9
+ static addImageLayer(map, imageData, options) {
10
+ const allowEmptyImg = !imageData.img && !!options?.layerName;
11
+ ValidationUtils.validateImageData(imageData, allowEmptyImg);
12
+ const mergedOptions = {
13
+ ...ConfigManager.DEFAULT_IMAGE_OPTIONS,
14
+ ...options
15
+ };
16
+ if (mergedOptions.layerName) {
17
+ const existingLayers = MapTools.getLayerByLayerName(map, mergedOptions.layerName);
18
+ if (existingLayers.length > 0) {
19
+ const existingLayer = existingLayers[0];
20
+ if (!imageData.extent) {
21
+ existingLayer.setSource(undefined);
22
+ }
23
+ else {
24
+ const url = imageData.img || existingLayer.getSource()?.getUrl() || '';
25
+ existingLayer.setSource(new ImageStatic({
26
+ url,
27
+ imageExtent: imageData.extent
28
+ }));
29
+ }
30
+ if (mergedOptions.opacity !== undefined)
31
+ existingLayer.setOpacity(mergedOptions.opacity);
32
+ if (mergedOptions.visible !== undefined)
33
+ existingLayer.setVisible(mergedOptions.visible);
34
+ if (mergedOptions.zIndex !== undefined)
35
+ existingLayer.setZIndex(mergedOptions.zIndex);
36
+ return existingLayer;
37
+ }
38
+ }
39
+ const source = imageData.extent
40
+ ? new ImageStatic({
41
+ url: imageData.img || '',
42
+ imageExtent: imageData.extent
43
+ })
44
+ : undefined;
45
+ const imageLayer = new ImageLayer({
46
+ source,
47
+ opacity: mergedOptions.opacity,
48
+ visible: mergedOptions.visible
49
+ });
50
+ imageLayer.set('name', mergedOptions.layerName);
51
+ imageLayer.set('layerName', mergedOptions.layerName);
52
+ imageLayer.setZIndex(mergedOptions.zIndex);
53
+ if (mergedOptions.mapClip && mergedOptions.mapClipData) {
54
+ const clippedLayer = MapTools.setMapClip(imageLayer, mergedOptions.mapClipData);
55
+ map.addLayer(clippedLayer);
56
+ return clippedLayer;
57
+ }
58
+ map.addLayer(imageLayer);
59
+ return imageLayer;
60
+ }
61
+ }