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,297 @@
1
+ import Feature from 'ol/Feature';
2
+ import { LineString, Point as OlPoint } from 'ol/geom';
3
+ import VectorLayer from 'ol/layer/Vector';
4
+ import VectorSource from 'ol/source/Vector';
5
+ import { getVectorContext } from 'ol/render';
6
+ import { unByKey } from 'ol/Observable';
7
+ import { ConfigManager } from '../map';
8
+ import LineFeatureFactory from './LineFeatureFactory';
9
+ import LineStyleFactory from './LineStyleFactory';
10
+ /**
11
+ * 流动线动画器
12
+ * 负责动画生命周期、postrender 与 RAF 驱动。
13
+ */
14
+ export default class LineFlowAnimator {
15
+ constructor(map, data, options = {}, onRemove) {
16
+ this.maxSymbolCount = 12;
17
+ this.styleFactory = new LineStyleFactory();
18
+ this.animationPointGeometry = new OlPoint([0, 0]);
19
+ this.animationPointFeature = new Feature(this.animationPointGeometry);
20
+ this.normalizedFeatures = [];
21
+ this.baseSource = new VectorSource();
22
+ this.animationSource = new VectorSource();
23
+ this.dashStyle = this.styleFactory.createDashStyle(ConfigManager.DEFAULT_FLOW_LINE_OPTIONS);
24
+ this.state = 'stopped';
25
+ this.startTime = 0;
26
+ this.pausedAt = 0;
27
+ this.pausedDuration = 0;
28
+ this.frozenProgress = 0;
29
+ this.rafId = null;
30
+ this.postrenderKey = null;
31
+ this.map = map;
32
+ this.onRemove = onRemove;
33
+ this.options = this.normalizeOptions(options);
34
+ this.normalizedFeatures = LineFeatureFactory.normalizeLineFeatures(data, this.options);
35
+ this.dashStyle = this.styleFactory.createDashStyle(this.options);
36
+ this.baseLayer = this.createBaseLayer();
37
+ this.animationLayer = this.createAnimationLayer();
38
+ this.updateSources(this.normalizedFeatures);
39
+ }
40
+ createHandle() {
41
+ if (this.normalizedFeatures.length === 0) {
42
+ return null;
43
+ }
44
+ this.map.addLayer(this.baseLayer);
45
+ this.map.addLayer(this.animationLayer);
46
+ if (this.options.autoStart) {
47
+ this.start();
48
+ }
49
+ return {
50
+ layer: this.baseLayer,
51
+ animationLayer: this.animationLayer,
52
+ start: () => this.start(),
53
+ pause: () => this.pause(),
54
+ resume: () => this.resume(),
55
+ stop: () => this.stop(),
56
+ setVisible: (visible) => this.setVisible(visible),
57
+ updateData: (data) => this.updateData(data),
58
+ remove: () => this.remove()
59
+ };
60
+ }
61
+ getProgressByTime(now, startTime, duration, speed, loop) {
62
+ const safeDuration = duration > 0 ? duration : ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.duration;
63
+ const safeSpeed = speed > 0 ? speed : 1;
64
+ const elapsed = Math.max(0, now - startTime) * safeSpeed;
65
+ const progress = elapsed / safeDuration;
66
+ if (loop) {
67
+ return progress % 1;
68
+ }
69
+ return Math.min(progress, 1);
70
+ }
71
+ getCoordinateAndRotation(line, progress) {
72
+ const safeProgress = Math.max(0, Math.min(progress, 1));
73
+ const epsilon = 0.0001;
74
+ const coordinate = line.getCoordinateAt(safeProgress);
75
+ const nextCoordinate = line.getCoordinateAt(Math.min(safeProgress + epsilon, 1));
76
+ const dx = nextCoordinate[0] - coordinate[0];
77
+ const dy = nextCoordinate[1] - coordinate[1];
78
+ return {
79
+ coordinate,
80
+ rotation: Math.atan2(dy, dx)
81
+ };
82
+ }
83
+ start() {
84
+ if (this.state === 'removed' || this.state === 'running' || this.normalizedFeatures.length === 0) {
85
+ return;
86
+ }
87
+ this.bindPostrender();
88
+ this.state = 'running';
89
+ this.startTime = this.getNow();
90
+ this.pausedAt = 0;
91
+ this.pausedDuration = 0;
92
+ this.frozenProgress = 0;
93
+ this.startRafLoop();
94
+ }
95
+ pause() {
96
+ if (this.state !== 'running') {
97
+ return;
98
+ }
99
+ this.frozenProgress = this.getCurrentProgress();
100
+ this.pausedAt = this.getNow();
101
+ this.state = 'paused';
102
+ this.stopRafLoop();
103
+ this.animationLayer.changed();
104
+ }
105
+ resume() {
106
+ if (this.state !== 'paused') {
107
+ return;
108
+ }
109
+ const now = this.getNow();
110
+ this.pausedDuration += now - this.pausedAt;
111
+ this.pausedAt = 0;
112
+ this.state = 'running';
113
+ this.bindPostrender();
114
+ this.startRafLoop();
115
+ }
116
+ stop() {
117
+ if (this.state === 'removed') {
118
+ return;
119
+ }
120
+ this.state = 'stopped';
121
+ this.frozenProgress = 0;
122
+ this.pausedAt = 0;
123
+ this.pausedDuration = 0;
124
+ this.startTime = 0;
125
+ this.stopRafLoop();
126
+ this.animationLayer.changed();
127
+ }
128
+ setVisible(visible) {
129
+ this.baseLayer.setVisible(visible);
130
+ this.animationLayer.setVisible(visible);
131
+ }
132
+ updateData(data) {
133
+ if (this.state === 'removed') {
134
+ return;
135
+ }
136
+ const nextFeatures = LineFeatureFactory.normalizeLineFeatures(data, this.options);
137
+ this.normalizedFeatures = nextFeatures;
138
+ this.updateSources(nextFeatures);
139
+ this.animationLayer.changed();
140
+ if (this.state === 'running') {
141
+ this.startRafLoop();
142
+ }
143
+ }
144
+ remove() {
145
+ if (this.state === 'removed') {
146
+ return;
147
+ }
148
+ this.stopRafLoop();
149
+ this.unbindPostrender();
150
+ this.normalizedFeatures = [];
151
+ this.baseSource.clear();
152
+ this.animationSource.clear();
153
+ this.styleFactory.clearCaches();
154
+ this.onRemove?.(this.options.layerName);
155
+ this.map.removeLayer(this.baseLayer);
156
+ this.map.removeLayer(this.animationLayer);
157
+ this.state = 'removed';
158
+ }
159
+ createBaseLayer() {
160
+ return new VectorLayer({
161
+ properties: {
162
+ name: this.options.layerName,
163
+ layerName: this.options.layerName
164
+ },
165
+ source: this.baseSource,
166
+ style: feature => this.styleFactory.getFlowBaseLineStyle(feature, this.options),
167
+ zIndex: this.options.zIndex
168
+ });
169
+ }
170
+ createAnimationLayer() {
171
+ return new VectorLayer({
172
+ properties: {
173
+ name: `${this.options.layerName}__flow-animation`,
174
+ layerName: `${this.options.layerName}__flow-animation`
175
+ },
176
+ source: this.animationSource,
177
+ style: () => this.styleFactory.getAnimationLayerStyle(this.options, this.dashStyle),
178
+ zIndex: this.options.zIndex + 1
179
+ });
180
+ }
181
+ normalizeOptions(options) {
182
+ const mergedOptions = {
183
+ ...ConfigManager.DEFAULT_FLOW_LINE_OPTIONS,
184
+ ...options
185
+ };
186
+ const flowSymbolOptions = {
187
+ ...ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.flowSymbol,
188
+ ...options.flowSymbol
189
+ };
190
+ return {
191
+ ...mergedOptions,
192
+ layerName: options.layerName || ConfigManager.DEFAULT_LINE_OPTIONS.layerName,
193
+ duration: mergedOptions.duration > 0 ? mergedOptions.duration : ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.duration,
194
+ loop: mergedOptions.loop ?? ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.loop,
195
+ autoStart: mergedOptions.autoStart ?? ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.autoStart,
196
+ showBaseLine: mergedOptions.showBaseLine ?? ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.showBaseLine,
197
+ animationMode: mergedOptions.animationMode ?? ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.animationMode,
198
+ trailEnabled: mergedOptions.trailEnabled ?? ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.trailEnabled,
199
+ trailLength: mergedOptions.trailLength ?? ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.trailLength,
200
+ speed: mergedOptions.speed && mergedOptions.speed > 0 ? mergedOptions.speed : 1,
201
+ zIndex: mergedOptions.zIndex ?? ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.zIndex,
202
+ flowSymbol: {
203
+ src: flowSymbolOptions.src,
204
+ scale: flowSymbolOptions.scale,
205
+ color: flowSymbolOptions.color,
206
+ rotateWithView: flowSymbolOptions.rotateWithView,
207
+ count: Math.min(this.maxSymbolCount, Math.max(1, Math.round(flowSymbolOptions.count))),
208
+ spacing: Math.max(0.01, Math.min(0.5, flowSymbolOptions.spacing))
209
+ }
210
+ };
211
+ }
212
+ updateSources(features) {
213
+ this.baseSource.clear();
214
+ this.animationSource.clear();
215
+ this.baseSource.addFeatures(LineFeatureFactory.cloneLineFeatures(features));
216
+ this.animationSource.addFeatures(LineFeatureFactory.cloneLineFeatures(features));
217
+ }
218
+ bindPostrender() {
219
+ if (this.postrenderKey || (this.options.animationMode !== 'icon' && this.options.animationMode !== 'icon+dash')) {
220
+ return;
221
+ }
222
+ this.postrenderKey = this.animationLayer.on('postrender', event => {
223
+ if (this.state === 'removed' || !this.animationLayer.getVisible()) {
224
+ return;
225
+ }
226
+ const vectorContext = getVectorContext(event);
227
+ const baseProgress = this.getCurrentProgress();
228
+ this.normalizedFeatures.forEach(feature => {
229
+ const geometry = feature.getGeometry();
230
+ if (!(geometry instanceof LineString)) {
231
+ return;
232
+ }
233
+ for (let symbolIndex = 0; symbolIndex < this.options.flowSymbol.count; symbolIndex += 1) {
234
+ const offsetProgress = baseProgress - (symbolIndex * this.options.flowSymbol.spacing);
235
+ const normalizedProgress = this.options.loop
236
+ ? ((offsetProgress % 1) + 1) % 1
237
+ : Math.max(0, Math.min(offsetProgress, 1));
238
+ if (!this.options.loop && (normalizedProgress <= 0 || normalizedProgress >= 1) && symbolIndex > 0) {
239
+ continue;
240
+ }
241
+ const { coordinate, rotation } = this.getCoordinateAndRotation(geometry, normalizedProgress);
242
+ this.animationPointGeometry.setCoordinates(coordinate);
243
+ const style = this.styleFactory.getMovingSymbolStyle(rotation, this.options);
244
+ vectorContext.setStyle(style);
245
+ vectorContext.drawFeature(this.animationPointFeature, style);
246
+ }
247
+ });
248
+ });
249
+ }
250
+ unbindPostrender() {
251
+ if (!this.postrenderKey) {
252
+ return;
253
+ }
254
+ unByKey(this.postrenderKey);
255
+ this.postrenderKey = null;
256
+ }
257
+ startRafLoop() {
258
+ if (this.rafId !== null) {
259
+ return;
260
+ }
261
+ const dashFallback = this.styleFactory.getDashFallback();
262
+ const renderFrame = () => {
263
+ if (this.state !== 'running') {
264
+ this.rafId = null;
265
+ return;
266
+ }
267
+ if (this.options.animationMode === 'dash' || this.options.animationMode === 'icon+dash') {
268
+ const dashOffset = -this.getCurrentProgress() * (this.options.lineDash?.reduce((sum, item) => sum + item, 0) ??
269
+ dashFallback.reduce((sum, item) => sum + item, 0));
270
+ this.dashStyle.getStroke()?.setLineDashOffset(dashOffset);
271
+ this.animationLayer.changed();
272
+ }
273
+ this.map.render();
274
+ this.rafId = requestAnimationFrame(renderFrame);
275
+ };
276
+ this.rafId = requestAnimationFrame(renderFrame);
277
+ }
278
+ stopRafLoop() {
279
+ if (this.rafId === null) {
280
+ return;
281
+ }
282
+ cancelAnimationFrame(this.rafId);
283
+ this.rafId = null;
284
+ }
285
+ getCurrentProgress() {
286
+ if (this.state === 'paused') {
287
+ return this.frozenProgress;
288
+ }
289
+ if (this.state === 'stopped' || this.startTime === 0) {
290
+ return 0;
291
+ }
292
+ return this.getProgressByTime(this.getNow() - this.pausedDuration, this.startTime, this.options.duration, this.options.speed, this.options.loop);
293
+ }
294
+ getNow() {
295
+ return typeof performance !== 'undefined' ? performance.now() : Date.now();
296
+ }
297
+ }
@@ -0,0 +1,43 @@
1
+ import Feature from 'ol/Feature';
2
+ import { LineString } from 'ol/geom';
3
+ import { Style } from 'ol/style';
4
+ import type { FeatureLike } from 'ol/Feature';
5
+ import type { FlowLineOptions, LineOptions } from '../../types';
6
+ /**
7
+ * 线样式工厂
8
+ * 负责静态线样式、流光虚线样式和 moving symbol 样式缓存。
9
+ */
10
+ export default class LineStyleFactory {
11
+ private readonly movingSymbolStyleCache;
12
+ private readonly baseLineStyle;
13
+ private readonly emptyStyle;
14
+ private readonly dashFallback;
15
+ /**
16
+ * 创建静态线样式解析函数。
17
+ */
18
+ createBaseLineStyleResolver(options: LineOptions): (feature: FeatureLike) => Style | Style[];
19
+ /**
20
+ * 创建流动线基础线样式。
21
+ */
22
+ getFlowBaseLineStyle(feature: Feature<LineString>, options: FlowLineOptions): Style | Style[] | void;
23
+ /**
24
+ * 创建流光虚线样式。
25
+ */
26
+ createDashStyle(options: FlowLineOptions): Style;
27
+ /**
28
+ * 创建动画图层样式。
29
+ */
30
+ getAnimationLayerStyle(options: FlowLineOptions, dashStyle: Style): Style;
31
+ /**
32
+ * 获取 moving symbol 样式,按旋转与配置做缓存。
33
+ */
34
+ getMovingSymbolStyle(rotation: number, options: FlowLineOptions): Style;
35
+ /**
36
+ * 清理样式缓存。
37
+ */
38
+ clearCaches(): void;
39
+ /**
40
+ * 获取 dash 默认总长度。
41
+ */
42
+ getDashFallback(): number[];
43
+ }
@@ -0,0 +1,135 @@
1
+ import Feature from 'ol/Feature';
2
+ import { Fill, Icon, RegularShape, Stroke, Style } from 'ol/style';
3
+ import { ConfigManager } from '../map';
4
+ /**
5
+ * 线样式工厂
6
+ * 负责静态线样式、流光虚线样式和 moving symbol 样式缓存。
7
+ */
8
+ export default class LineStyleFactory {
9
+ constructor() {
10
+ this.movingSymbolStyleCache = new globalThis.Map();
11
+ this.baseLineStyle = new Style();
12
+ this.emptyStyle = new Style();
13
+ this.dashFallback = [12, 12];
14
+ }
15
+ /**
16
+ * 创建静态线样式解析函数。
17
+ */
18
+ createBaseLineStyleResolver(options) {
19
+ return (feature) => {
20
+ if (feature instanceof Feature) {
21
+ feature.set('type', options.type);
22
+ feature.set('layerName', options.layerName);
23
+ }
24
+ if (options.style) {
25
+ if (typeof options.style === 'function') {
26
+ return options.style(feature);
27
+ }
28
+ return options.style;
29
+ }
30
+ this.baseLineStyle.setStroke(new Stroke({
31
+ color: options.strokeColor ?? ConfigManager.DEFAULT_LINE_OPTIONS.strokeColor,
32
+ width: options.strokeWidth ?? ConfigManager.DEFAULT_LINE_OPTIONS.strokeWidth,
33
+ lineDash: options.lineDash,
34
+ lineDashOffset: options.lineDashOffset
35
+ }));
36
+ return this.baseLineStyle;
37
+ };
38
+ }
39
+ /**
40
+ * 创建流动线基础线样式。
41
+ */
42
+ getFlowBaseLineStyle(feature, options) {
43
+ if (!options.showBaseLine) {
44
+ this.baseLineStyle.setStroke(new Stroke({ color: 'rgba(0,0,0,0)', width: 0 }));
45
+ return this.baseLineStyle;
46
+ }
47
+ if (options.style) {
48
+ if (typeof options.style === 'function') {
49
+ return options.style(feature);
50
+ }
51
+ return options.style;
52
+ }
53
+ this.baseLineStyle.setStroke(new Stroke({
54
+ color: options.strokeColor ?? ConfigManager.DEFAULT_LINE_OPTIONS.strokeColor,
55
+ width: options.strokeWidth ?? ConfigManager.DEFAULT_LINE_OPTIONS.strokeWidth,
56
+ lineDash: options.lineDash,
57
+ lineDashOffset: options.lineDashOffset
58
+ }));
59
+ return this.baseLineStyle;
60
+ }
61
+ /**
62
+ * 创建流光虚线样式。
63
+ */
64
+ createDashStyle(options) {
65
+ const lineDash = options.lineDash && options.lineDash.length > 0 ? options.lineDash : this.dashFallback;
66
+ return new Style({
67
+ stroke: new Stroke({
68
+ color: options.strokeColor ?? ConfigManager.DEFAULT_LINE_OPTIONS.strokeColor,
69
+ width: options.strokeWidth ?? ConfigManager.DEFAULT_LINE_OPTIONS.strokeWidth,
70
+ lineDash,
71
+ lineDashOffset: options.lineDashOffset ?? 0
72
+ })
73
+ });
74
+ }
75
+ /**
76
+ * 创建动画图层样式。
77
+ */
78
+ getAnimationLayerStyle(options, dashStyle) {
79
+ if (options.animationMode === 'icon') {
80
+ return this.emptyStyle;
81
+ }
82
+ return dashStyle;
83
+ }
84
+ /**
85
+ * 获取 moving symbol 样式,按旋转与配置做缓存。
86
+ */
87
+ getMovingSymbolStyle(rotation, options) {
88
+ const flowSymbol = options.flowSymbol ?? {};
89
+ const cacheKey = [
90
+ rotation.toFixed(2),
91
+ flowSymbol.src ?? 'builtin',
92
+ flowSymbol.scale ?? ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.flowSymbol.scale,
93
+ flowSymbol.color ?? options.strokeColor ?? ConfigManager.DEFAULT_LINE_OPTIONS.strokeColor,
94
+ String(flowSymbol.rotateWithView ?? ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.flowSymbol.rotateWithView)
95
+ ].join('|');
96
+ const cachedStyle = this.movingSymbolStyleCache.get(cacheKey);
97
+ if (cachedStyle) {
98
+ return cachedStyle;
99
+ }
100
+ const color = flowSymbol.color ?? options.strokeColor ?? ConfigManager.DEFAULT_LINE_OPTIONS.strokeColor;
101
+ const scale = flowSymbol.scale ?? ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.flowSymbol.scale;
102
+ const rotateWithView = flowSymbol.rotateWithView ?? ConfigManager.DEFAULT_FLOW_LINE_OPTIONS.flowSymbol.rotateWithView;
103
+ const image = flowSymbol.src
104
+ ? new Icon({
105
+ src: flowSymbol.src,
106
+ scale,
107
+ color: flowSymbol.color,
108
+ rotation,
109
+ rotateWithView
110
+ })
111
+ : new RegularShape({
112
+ points: 3,
113
+ radius: 10 * scale,
114
+ rotation: rotation - Math.PI / 2,
115
+ rotateWithView,
116
+ fill: new Fill({ color }),
117
+ stroke: new Stroke({ color, width: 1 })
118
+ });
119
+ const style = new Style({ image });
120
+ this.movingSymbolStyleCache.set(cacheKey, style);
121
+ return style;
122
+ }
123
+ /**
124
+ * 清理样式缓存。
125
+ */
126
+ clearCaches() {
127
+ this.movingSymbolStyleCache.clear();
128
+ }
129
+ /**
130
+ * 获取 dash 默认总长度。
131
+ */
132
+ getDashFallback() {
133
+ return this.dashFallback;
134
+ }
135
+ }
@@ -1,8 +1,8 @@
1
1
  import Map from "ol/Map";
2
2
  import VectorSource from "ol/source/Vector";
3
3
  import VectorLayer from "ol/layer/Vector";
4
- import { LineOptions, MapJSONData } from "../types";
5
- import { EventManager } from "./EventManager";
4
+ import { LineOptions, MapJSONData } from "../../types";
5
+ import { EventManager } from "../map";
6
6
  /**
7
7
  * 河流图层管理类
8
8
  * 用于创建与管理河流相关矢量图层(分级显示、按级别线宽、显示控制与清理)
@@ -3,11 +3,9 @@ import GeoJSON from "ol/format/GeoJSON";
3
3
  import VectorLayer from "ol/layer/Vector";
4
4
  import { Stroke, Style } from "ol/style";
5
5
  import { Feature } from "ol";
6
- import MapTools from "./MapTools";
7
- import { ValidationUtils } from "../utils/ValidationUtils";
8
- import { EventManager } from "./EventManager";
9
- import { ErrorHandler } from "../utils/ErrorHandler";
10
- import { ConfigManager } from "./ConfigManager";
6
+ import ValidationUtils from "../../utils/ValidationUtils";
7
+ import { ErrorHandler } from "../../utils/ErrorHandler";
8
+ import { ConfigManager, EventManager, MapTools } from "../map";
11
9
  export default class RiverLayerManager {
12
10
  /**
13
11
  * 构造函数
@@ -0,0 +1,6 @@
1
+ export { default as Line } from './Line';
2
+ export { default as LineFlowAnimator } from './LineFlowAnimator';
3
+ export { default as LineFeatureFactory } from './LineFeatureFactory';
4
+ export { default as LineStyleFactory } from './LineStyleFactory';
5
+ export { default as RiverLayerManager } from './RiverLayerManager';
6
+ export type { RiverLayerOptions, RiverLevelWidthMap } from './RiverLayerManager';
@@ -0,0 +1,5 @@
1
+ export { default as Line } from './Line';
2
+ export { default as LineFlowAnimator } from './LineFlowAnimator';
3
+ export { default as LineFeatureFactory } from './LineFeatureFactory';
4
+ export { default as LineStyleFactory } from './LineStyleFactory';
5
+ export { default as RiverLayerManager } from './RiverLayerManager';
@@ -2,7 +2,7 @@
2
2
  * 配置管理类
3
3
  * 用于统一管理默认配置和验证
4
4
  */
5
- export declare class ConfigManager {
5
+ export default class ConfigManager {
6
6
  /**
7
7
  * 默认点位配置
8
8
  */
@@ -38,6 +38,30 @@ export declare class ConfigManager {
38
38
  layerName: string;
39
39
  zIndex: number;
40
40
  };
41
+ /**
42
+ * 默认流动线动画配置
43
+ */
44
+ static readonly DEFAULT_FLOW_LINE_OPTIONS: {
45
+ readonly duration: 4000;
46
+ readonly loop: true;
47
+ readonly autoStart: true;
48
+ readonly showBaseLine: true;
49
+ readonly animationMode: "icon";
50
+ readonly flowSymbol: {
51
+ readonly scale: 0.8;
52
+ readonly rotateWithView: true;
53
+ readonly count: 1;
54
+ readonly spacing: 0.15;
55
+ };
56
+ readonly trailEnabled: false;
57
+ readonly trailLength: 0;
58
+ readonly zIndex: 16;
59
+ readonly type: string;
60
+ readonly strokeColor: string;
61
+ readonly strokeWidth: number;
62
+ readonly visible: boolean;
63
+ readonly layerName: string;
64
+ };
41
65
  /**
42
66
  * 默认面配置
43
67
  */
@@ -2,7 +2,7 @@
2
2
  * 配置管理类
3
3
  * 用于统一管理默认配置和验证
4
4
  */
5
- export class ConfigManager {
5
+ class ConfigManager {
6
6
  /**
7
7
  * 合并配置选项
8
8
  * @param defaultOptions 默认配置
@@ -82,6 +82,26 @@ ConfigManager.DEFAULT_LINE_OPTIONS = {
82
82
  layerName: 'lineLayer',
83
83
  zIndex: 15
84
84
  };
85
+ /**
86
+ * 默认流动线动画配置
87
+ */
88
+ ConfigManager.DEFAULT_FLOW_LINE_OPTIONS = {
89
+ ...ConfigManager.DEFAULT_LINE_OPTIONS,
90
+ duration: 4000,
91
+ loop: true,
92
+ autoStart: true,
93
+ showBaseLine: true,
94
+ animationMode: 'icon',
95
+ flowSymbol: {
96
+ scale: 0.8,
97
+ rotateWithView: true,
98
+ count: 1,
99
+ spacing: 0.15
100
+ },
101
+ trailEnabled: false,
102
+ trailLength: 0,
103
+ zIndex: 16
104
+ };
85
105
  /**
86
106
  * 默认面配置
87
107
  */
@@ -184,3 +204,4 @@ ConfigManager.DEFAULT_RIVER_WIDTH_BY_LEVEL_OPTIONS = {
184
204
  zIndex: 15,
185
205
  removeExisting: false
186
206
  };
207
+ export default ConfigManager;
@@ -26,7 +26,7 @@ export interface MapEventData {
26
26
  * 事件管理器类
27
27
  * 用于统一管理地图事件的注册、触发和移除
28
28
  */
29
- export declare class EventManager {
29
+ export default class EventManager {
30
30
  private readonly map;
31
31
  private listeners;
32
32
  private eventCounters;
@@ -1,9 +1,9 @@
1
- import { ErrorHandler, ErrorType } from '../utils/ErrorHandler';
1
+ import { ErrorHandler, ErrorType } from '../../utils/ErrorHandler';
2
2
  /**
3
3
  * 事件管理器类
4
4
  * 用于统一管理地图事件的注册、触发和移除
5
5
  */
6
- export class EventManager {
6
+ export default class EventManager {
7
7
  /**
8
8
  * 构造函数
9
9
  * @param map OpenLayers地图实例
@@ -8,7 +8,7 @@ import { Tile as TileLayer } from "ol/layer";
8
8
  import { TileWMS } from "ol/source";
9
9
  import WMTSTileGrid from "ol/tilegrid/WMTS";
10
10
  import XYZ from "ol/source/XYZ";
11
- import { MapLayersOptions, TiandituType, AnnotationLayerOptions, AnnotationType } from "../types";
11
+ import { MapLayersOptions, TiandituType, AnnotationLayerOptions, AnnotationType } from "../../types";
12
12
  /**
13
13
  * GeoServer图层选项接口
14
14
  */
@@ -10,9 +10,9 @@ import { TileWMS } from "ol/source";
10
10
  import WMTSTileGrid from "ol/tilegrid/WMTS";
11
11
  import XYZ from "ol/source/XYZ";
12
12
  import MapTools from "./MapTools";
13
- import { ErrorHandler, ErrorType } from "../utils/ErrorHandler";
14
- import { ValidationUtils } from "../utils/ValidationUtils";
15
- import { ConfigManager } from "./ConfigManager";
13
+ import { ErrorHandler, ErrorType } from "../../utils/ErrorHandler";
14
+ import ValidationUtils from "../../utils/ValidationUtils";
15
+ import ConfigManager from "./ConfigManager";
16
16
  const TIANDITU_TYPES = ['vec_c', 'img_c', 'ter_c'];
17
17
  const CUSTOM_LAYER_KEY = '__custom__';
18
18
  /**
@@ -1,5 +1,5 @@
1
1
  import Map from "ol/Map";
2
- import { MapJSONData } from "../types";
2
+ import { MapJSONData } from "../../types";
3
3
  import VectorLayer from "ol/layer/Vector";
4
4
  import VectorSource from "ol/source/Vector";
5
5
  import BaseLayer from "ol/layer/Base";
@@ -70,7 +70,10 @@ export default class MapTools {
70
70
  * @param duration 动画时长
71
71
  * @returns 定位是否成功
72
72
  */
73
- locationAction(lgtd: number, lttd: number, zoom?: number, duration?: number): boolean;
73
+ locationAction(lgtd: number, lttd: number, zoom?: number, duration?: number, projection?: {
74
+ dataProjection?: string;
75
+ featureProjection?: string;
76
+ }): boolean;
74
77
  /**
75
78
  * 获取地图实例
76
79
  * @returns 地图实例