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
@@ -0,0 +1,53 @@
1
+ import Map from 'ol/Map';
2
+ import { LineString } from 'ol/geom';
3
+ import type { FlowLineLayerHandle, FlowLineOptions } from '../../types';
4
+ /**
5
+ * 流动线动画器
6
+ * 负责动画生命周期、postrender 与 RAF 驱动。
7
+ */
8
+ export default class LineFlowAnimator {
9
+ private readonly map;
10
+ private readonly onRemove?;
11
+ private readonly maxSymbolCount;
12
+ private readonly styleFactory;
13
+ private readonly animationPointGeometry;
14
+ private readonly animationPointFeature;
15
+ private options;
16
+ private normalizedFeatures;
17
+ private baseSource;
18
+ private animationSource;
19
+ private baseLayer;
20
+ private animationLayer;
21
+ private dashStyle;
22
+ private state;
23
+ private startTime;
24
+ private pausedAt;
25
+ private pausedDuration;
26
+ private frozenProgress;
27
+ private rafId;
28
+ private postrenderKey;
29
+ constructor(map: Map, data: unknown, options?: FlowLineOptions, onRemove?: (layerName: string) => void);
30
+ createHandle(): FlowLineLayerHandle | null;
31
+ getProgressByTime(now: number, startTime: number, duration: number, speed: number, loop: boolean): number;
32
+ getCoordinateAndRotation(line: LineString, progress: number): {
33
+ coordinate: number[];
34
+ rotation: number;
35
+ };
36
+ start(): void;
37
+ pause(): void;
38
+ resume(): void;
39
+ stop(): void;
40
+ setVisible(visible: boolean): void;
41
+ updateData(data: unknown): void;
42
+ remove(): void;
43
+ private createBaseLayer;
44
+ private createAnimationLayer;
45
+ private normalizeOptions;
46
+ private updateSources;
47
+ private bindPostrender;
48
+ private unbindPostrender;
49
+ private startRafLoop;
50
+ private stopRafLoop;
51
+ private getCurrentProgress;
52
+ private getNow;
53
+ }
@@ -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
  */