@angular-helpers/openlayers 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/angular-helpers-openlayers-controls.mjs +496 -107
- package/fesm2022/angular-helpers-openlayers-core.mjs +130 -32
- package/fesm2022/angular-helpers-openlayers-interactions.mjs +583 -10
- package/fesm2022/angular-helpers-openlayers-layers.mjs +318 -49
- package/package.json +2 -1
- package/types/angular-helpers-openlayers-controls.d.ts +161 -23
- package/types/angular-helpers-openlayers-core.d.ts +72 -7
- package/types/angular-helpers-openlayers-interactions.d.ts +315 -6
- package/types/angular-helpers-openlayers-layers.d.ts +61 -10
|
@@ -1,29 +1,51 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Injectable, input, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
2
|
+
import { inject, signal, computed, Injectable, DestroyRef, input, afterNextRender, effect, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
3
|
import VectorLayer from 'ol/layer/Vector';
|
|
4
4
|
import TileLayer from 'ol/layer/Tile';
|
|
5
5
|
import ImageLayer from 'ol/layer/Image';
|
|
6
6
|
import VectorSource from 'ol/source/Vector';
|
|
7
|
+
import { Feature } from 'ol';
|
|
8
|
+
import { Point, LineString, Polygon, Circle } from 'ol/geom';
|
|
9
|
+
import { fromLonLat } from 'ol/proj';
|
|
10
|
+
import { Style, Circle as Circle$1, Stroke, Fill } from 'ol/style';
|
|
7
11
|
import OSM from 'ol/source/OSM';
|
|
8
12
|
import XYZ from 'ol/source/XYZ';
|
|
9
13
|
import TileWMS from 'ol/source/TileWMS';
|
|
10
14
|
import ImageWMS from 'ol/source/ImageWMS';
|
|
15
|
+
import { ImageStatic } from 'ol/source';
|
|
11
16
|
import { OlMapService } from '@angular-helpers/openlayers/core';
|
|
12
17
|
|
|
13
18
|
// OlLayerService
|
|
14
19
|
class OlLayerService {
|
|
15
20
|
mapService = inject(OlMapService);
|
|
16
21
|
layerCache = new Map();
|
|
22
|
+
pendingConfigs = [];
|
|
23
|
+
layerState = signal([], ...(ngDevMode ? [{ debugName: "layerState" }] : /* istanbul ignore next */ []));
|
|
24
|
+
layers = computed(() => this.layerState(), ...(ngDevMode ? [{ debugName: "layers" }] : /* istanbul ignore next */ []));
|
|
25
|
+
visibleLayers = computed(() => this.layerState().filter((l) => l.visible), ...(ngDevMode ? [{ debugName: "visibleLayers" }] : /* istanbul ignore next */ []));
|
|
26
|
+
tileLayers = computed(() => this.layerState().filter((l) => l.type === 'tile'), ...(ngDevMode ? [{ debugName: "tileLayers" }] : /* istanbul ignore next */ []));
|
|
27
|
+
vectorLayers = computed(() => this.layerState().filter((l) => l.type === 'vector'), ...(ngDevMode ? [{ debugName: "vectorLayers" }] : /* istanbul ignore next */ []));
|
|
17
28
|
addLayer(config) {
|
|
18
|
-
// If layer already exists, return it (idempotent for retries)
|
|
19
29
|
if (this.layerCache.has(config.id)) {
|
|
20
30
|
return { id: config.id };
|
|
21
31
|
}
|
|
22
32
|
const map = this.mapService.getMap();
|
|
23
33
|
if (!map) {
|
|
24
|
-
|
|
34
|
+
this.pendingConfigs.push(config);
|
|
35
|
+
this.mapService.onReady((readyMap) => this.flushPending(readyMap));
|
|
25
36
|
return { id: config.id };
|
|
26
37
|
}
|
|
38
|
+
return this.createLayer(config, map);
|
|
39
|
+
}
|
|
40
|
+
flushPending(map) {
|
|
41
|
+
const pending = this.pendingConfigs.splice(0);
|
|
42
|
+
for (const config of pending) {
|
|
43
|
+
if (!this.layerCache.has(config.id)) {
|
|
44
|
+
this.createLayer(config, map);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
createLayer(config, map) {
|
|
27
49
|
switch (config.type) {
|
|
28
50
|
case 'vector':
|
|
29
51
|
return this.createVectorLayer(config, map);
|
|
@@ -35,30 +57,213 @@ class OlLayerService {
|
|
|
35
57
|
return { id: config.id };
|
|
36
58
|
}
|
|
37
59
|
}
|
|
60
|
+
getLayer(id) {
|
|
61
|
+
return this.layerCache.get(id);
|
|
62
|
+
}
|
|
63
|
+
hasLayer(id) {
|
|
64
|
+
return this.layerCache.has(id);
|
|
65
|
+
}
|
|
38
66
|
removeLayer(id) {
|
|
67
|
+
// Cancel if it's still pending (map not ready yet)
|
|
68
|
+
const pendingIdx = this.pendingConfigs.findIndex((c) => c.id === id);
|
|
69
|
+
if (pendingIdx !== -1) {
|
|
70
|
+
this.pendingConfigs.splice(pendingIdx, 1);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
39
73
|
const map = this.mapService.getMap();
|
|
40
74
|
const layer = this.layerCache.get(id);
|
|
41
75
|
if (map && layer) {
|
|
42
76
|
map.removeLayer(layer);
|
|
43
77
|
this.layerCache.delete(id);
|
|
78
|
+
this.updateLayerState();
|
|
44
79
|
}
|
|
45
80
|
}
|
|
46
81
|
setVisibility(id, visible) {
|
|
47
|
-
this.layerCache.get(id)
|
|
82
|
+
const layer = this.layerCache.get(id);
|
|
83
|
+
if (layer) {
|
|
84
|
+
layer.setVisible(visible);
|
|
85
|
+
this.updateLayerState();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
toggleVisibility(id) {
|
|
89
|
+
const layer = this.layerCache.get(id);
|
|
90
|
+
if (layer) {
|
|
91
|
+
const newVisible = !layer.getVisible();
|
|
92
|
+
layer.setVisible(newVisible);
|
|
93
|
+
this.updateLayerState();
|
|
94
|
+
return newVisible;
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
48
97
|
}
|
|
49
98
|
setOpacity(id, opacity) {
|
|
50
|
-
this.layerCache.get(id)
|
|
99
|
+
const layer = this.layerCache.get(id);
|
|
100
|
+
if (layer) {
|
|
101
|
+
layer.setOpacity(opacity);
|
|
102
|
+
this.updateLayerState();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
setZIndex(id, zIndex) {
|
|
106
|
+
const layer = this.layerCache.get(id);
|
|
107
|
+
if (layer) {
|
|
108
|
+
layer.setZIndex(zIndex);
|
|
109
|
+
this.updateLayerState();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
isVisible(id) {
|
|
113
|
+
return this.layerCache.get(id)?.getVisible() ?? false;
|
|
114
|
+
}
|
|
115
|
+
getOpacity(id) {
|
|
116
|
+
return this.layerCache.get(id)?.getOpacity() ?? 1;
|
|
117
|
+
}
|
|
118
|
+
getZIndex(id) {
|
|
119
|
+
return this.layerCache.get(id)?.getZIndex() ?? 0;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Clears all features from a vector layer's source.
|
|
123
|
+
* Does not remove the layer itself.
|
|
124
|
+
* @param id - Layer identifier
|
|
125
|
+
*/
|
|
126
|
+
clearFeatures(id) {
|
|
127
|
+
const layer = this.layerCache.get(id);
|
|
128
|
+
if (!(layer instanceof VectorLayer))
|
|
129
|
+
return;
|
|
130
|
+
layer.getSource()?.clear();
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Updates the features of a vector layer.
|
|
134
|
+
* Syncs new features without clearing existing ones (preserves OL modifications).
|
|
135
|
+
* @param id - Layer identifier
|
|
136
|
+
* @param features - New features to sync
|
|
137
|
+
*/
|
|
138
|
+
updateFeatures(id, features) {
|
|
139
|
+
const layer = this.layerCache.get(id);
|
|
140
|
+
if (!(layer instanceof VectorLayer))
|
|
141
|
+
return;
|
|
142
|
+
const source = layer.getSource();
|
|
143
|
+
if (!source)
|
|
144
|
+
return;
|
|
145
|
+
// Get existing feature IDs from source
|
|
146
|
+
const existingIds = new Set(source
|
|
147
|
+
.getFeatures()
|
|
148
|
+
.map((f) => f.getId())
|
|
149
|
+
.filter((id) => id !== undefined));
|
|
150
|
+
// Only add features that don't already exist in the source
|
|
151
|
+
if (features && features.length > 0) {
|
|
152
|
+
const newFeatures = features.filter((f) => !existingIds.has(f.id));
|
|
153
|
+
if (newFeatures.length > 0) {
|
|
154
|
+
const olFeatures = newFeatures.map((feature) => {
|
|
155
|
+
const geom = feature.geometry;
|
|
156
|
+
let geometry;
|
|
157
|
+
// Validate coordinates exist before processing
|
|
158
|
+
if (!geom.coordinates) {
|
|
159
|
+
geometry = new Point([0, 0]);
|
|
160
|
+
}
|
|
161
|
+
else if (geom.type === 'Point') {
|
|
162
|
+
const coords = geom.coordinates;
|
|
163
|
+
geometry = new Point(fromLonLat(coords));
|
|
164
|
+
}
|
|
165
|
+
else if (geom.type === 'LineString') {
|
|
166
|
+
const coords = geom.coordinates.map((c) => fromLonLat(c));
|
|
167
|
+
geometry = new LineString(coords);
|
|
168
|
+
}
|
|
169
|
+
else if (geom.type === 'Polygon') {
|
|
170
|
+
const rings = geom.coordinates.map((ring) => ring.map((c) => fromLonLat(c)));
|
|
171
|
+
geometry = new Polygon(rings);
|
|
172
|
+
}
|
|
173
|
+
else if (geom.type === 'Circle') {
|
|
174
|
+
const center = fromLonLat(geom.coordinates);
|
|
175
|
+
// Approximate radius in meters - use 1000m as default if not specified
|
|
176
|
+
geometry = new Circle(center, geom.radius ?? 1000);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
geometry = new Point([0, 0]);
|
|
180
|
+
}
|
|
181
|
+
const olFeature = new Feature({
|
|
182
|
+
geometry,
|
|
183
|
+
...feature.properties,
|
|
184
|
+
});
|
|
185
|
+
olFeature.setId(feature.id);
|
|
186
|
+
return olFeature;
|
|
187
|
+
});
|
|
188
|
+
source.addFeatures(olFeatures);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
updateLayerState() {
|
|
193
|
+
const layers = [];
|
|
194
|
+
this.layerCache.forEach((layer, id) => {
|
|
195
|
+
const type = layer instanceof VectorLayer ? 'vector' : layer instanceof TileLayer ? 'tile' : 'image';
|
|
196
|
+
layers.push({
|
|
197
|
+
id,
|
|
198
|
+
type: type,
|
|
199
|
+
visible: layer.getVisible(),
|
|
200
|
+
opacity: layer.getOpacity(),
|
|
201
|
+
zIndex: layer.getZIndex() ?? 0,
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
this.layerState.set(layers.sort((a, b) => a.zIndex - b.zIndex));
|
|
51
205
|
}
|
|
52
206
|
createVectorLayer(config, map) {
|
|
207
|
+
const source = new VectorSource();
|
|
208
|
+
// Add features if provided
|
|
209
|
+
if (config.features && config.features.length > 0) {
|
|
210
|
+
const olFeatures = config.features.map((feature) => {
|
|
211
|
+
const geom = feature.geometry;
|
|
212
|
+
let geometry;
|
|
213
|
+
// Validate coordinates exist before processing
|
|
214
|
+
if (!geom.coordinates) {
|
|
215
|
+
geometry = new Point([0, 0]);
|
|
216
|
+
}
|
|
217
|
+
else if (geom.type === 'Point') {
|
|
218
|
+
// Transform from EPSG:4326 (lon/lat) to EPSG:3857 (map projection)
|
|
219
|
+
const coords = geom.coordinates;
|
|
220
|
+
geometry = new Point(fromLonLat(coords));
|
|
221
|
+
}
|
|
222
|
+
else if (geom.type === 'LineString') {
|
|
223
|
+
const coords = geom.coordinates.map((c) => fromLonLat(c));
|
|
224
|
+
geometry = new LineString(coords);
|
|
225
|
+
}
|
|
226
|
+
else if (geom.type === 'Polygon') {
|
|
227
|
+
const rings = geom.coordinates.map((ring) => ring.map((c) => fromLonLat(c)));
|
|
228
|
+
geometry = new Polygon(rings);
|
|
229
|
+
}
|
|
230
|
+
else if (geom.type === 'Circle') {
|
|
231
|
+
const center = fromLonLat(geom.coordinates);
|
|
232
|
+
geometry = new Circle(center, geom.radius ?? 1000);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
geometry = new Point([0, 0]);
|
|
236
|
+
}
|
|
237
|
+
const olFeature = new Feature({
|
|
238
|
+
geometry,
|
|
239
|
+
...feature.properties,
|
|
240
|
+
});
|
|
241
|
+
olFeature.setId(feature.id);
|
|
242
|
+
return olFeature;
|
|
243
|
+
});
|
|
244
|
+
source.addFeatures(olFeatures);
|
|
245
|
+
}
|
|
246
|
+
// Default style for all geometry types (points, lines, polygons)
|
|
247
|
+
const defaultStyle = new Style({
|
|
248
|
+
fill: new Fill({ color: 'rgba(25, 118, 210, 0.3)' }),
|
|
249
|
+
stroke: new Stroke({ color: '#1976d2', width: 2 }),
|
|
250
|
+
image: new Circle$1({
|
|
251
|
+
radius: 8,
|
|
252
|
+
fill: new Fill({ color: '#1976d2' }),
|
|
253
|
+
stroke: new Stroke({ color: '#d32f2f', width: 2 }),
|
|
254
|
+
}),
|
|
255
|
+
});
|
|
53
256
|
const layer = new VectorLayer({
|
|
54
|
-
source
|
|
257
|
+
source,
|
|
55
258
|
visible: config.visible ?? true,
|
|
56
259
|
opacity: config.opacity ?? 1,
|
|
57
260
|
zIndex: config.zIndex,
|
|
261
|
+
style: defaultStyle,
|
|
58
262
|
});
|
|
59
263
|
layer.set('id', config.id);
|
|
60
264
|
map.addLayer(layer);
|
|
61
265
|
this.layerCache.set(config.id, layer);
|
|
266
|
+
this.updateLayerState();
|
|
62
267
|
return { id: config.id };
|
|
63
268
|
}
|
|
64
269
|
createTileLayer(config, map) {
|
|
@@ -89,10 +294,20 @@ class OlLayerService {
|
|
|
89
294
|
layer.set('id', config.id);
|
|
90
295
|
map.addLayer(layer);
|
|
91
296
|
this.layerCache.set(config.id, layer);
|
|
297
|
+
this.updateLayerState();
|
|
92
298
|
return { id: config.id };
|
|
93
299
|
}
|
|
94
300
|
createImageLayer(config, map) {
|
|
95
|
-
|
|
301
|
+
let source;
|
|
302
|
+
if (config.source.type === 'static') {
|
|
303
|
+
source = new ImageStatic({
|
|
304
|
+
url: config.source.url,
|
|
305
|
+
imageExtent: config.source.imageExtent ?? [0, 0, 1, 1],
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
source = new ImageWMS({ url: config.source.url, params: config.source.params });
|
|
310
|
+
}
|
|
96
311
|
const layer = new ImageLayer({
|
|
97
312
|
source,
|
|
98
313
|
visible: config.visible ?? true,
|
|
@@ -102,6 +317,7 @@ class OlLayerService {
|
|
|
102
317
|
layer.set('id', config.id);
|
|
103
318
|
map.addLayer(layer);
|
|
104
319
|
this.layerCache.set(config.id, layer);
|
|
320
|
+
this.updateLayerState();
|
|
105
321
|
return { id: config.id };
|
|
106
322
|
}
|
|
107
323
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: OlLayerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -114,25 +330,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
114
330
|
// OlVectorLayerComponent
|
|
115
331
|
class OlVectorLayerComponent {
|
|
116
332
|
layerService = inject(OlLayerService);
|
|
333
|
+
destroyRef = inject(DestroyRef);
|
|
117
334
|
id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
118
335
|
features = input([], ...(ngDevMode ? [{ debugName: "features" }] : /* istanbul ignore next */ []));
|
|
119
336
|
zIndex = input(0, ...(ngDevMode ? [{ debugName: "zIndex" }] : /* istanbul ignore next */ []));
|
|
120
337
|
opacity = input(1, ...(ngDevMode ? [{ debugName: "opacity" }] : /* istanbul ignore next */ []));
|
|
121
338
|
visible = input(true, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
122
339
|
style = input(...(ngDevMode ? [undefined, { debugName: "style" }] : /* istanbul ignore next */ []));
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
340
|
+
constructor() {
|
|
341
|
+
// Initialize layer after DOM is ready
|
|
342
|
+
afterNextRender(() => {
|
|
343
|
+
this.layerService.addLayer({
|
|
344
|
+
id: this.id(),
|
|
345
|
+
type: 'vector',
|
|
346
|
+
features: this.features(),
|
|
347
|
+
zIndex: this.zIndex(),
|
|
348
|
+
opacity: this.opacity(),
|
|
349
|
+
visible: this.visible(),
|
|
350
|
+
style: this.style(),
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
// Effect to sync features when input changes
|
|
354
|
+
effect(() => {
|
|
355
|
+
const currentFeatures = this.features();
|
|
356
|
+
// Only update if layer already exists (afterNextRender already created it)
|
|
357
|
+
if (this.layerService.getLayer(this.id())) {
|
|
358
|
+
this.layerService.updateFeatures(this.id(), currentFeatures);
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
// Cleanup when component is destroyed
|
|
362
|
+
this.destroyRef.onDestroy(() => {
|
|
363
|
+
this.layerService.removeLayer(this.id());
|
|
132
364
|
});
|
|
133
|
-
}
|
|
134
|
-
ngOnDestroy() {
|
|
135
|
-
this.layerService.removeLayer(this.id());
|
|
136
365
|
}
|
|
137
366
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: OlVectorLayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
138
367
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: OlVectorLayerComponent, isStandalone: true, selector: "ol-vector-layer", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, features: { classPropertyName: "features", publicName: "features", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, opacity: { classPropertyName: "opacity", publicName: "opacity", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -144,11 +373,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
144
373
|
template: '',
|
|
145
374
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
146
375
|
}]
|
|
147
|
-
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], features: [{ type: i0.Input, args: [{ isSignal: true, alias: "features", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }] } });
|
|
376
|
+
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], features: [{ type: i0.Input, args: [{ isSignal: true, alias: "features", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }] } });
|
|
148
377
|
|
|
149
378
|
// OlTileLayerComponent
|
|
150
379
|
class OlTileLayerComponent {
|
|
151
380
|
layerService = inject(OlLayerService);
|
|
381
|
+
destroyRef = inject(DestroyRef);
|
|
152
382
|
id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
153
383
|
source = input.required(...(ngDevMode ? [{ debugName: "source" }] : /* istanbul ignore next */ []));
|
|
154
384
|
url = input(...(ngDevMode ? [undefined, { debugName: "url" }] : /* istanbul ignore next */ []));
|
|
@@ -157,34 +387,27 @@ class OlTileLayerComponent {
|
|
|
157
387
|
zIndex = input(0, ...(ngDevMode ? [{ debugName: "zIndex" }] : /* istanbul ignore next */ []));
|
|
158
388
|
opacity = input(1, ...(ngDevMode ? [{ debugName: "opacity" }] : /* istanbul ignore next */ []));
|
|
159
389
|
visible = input(true, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
160
|
-
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
390
|
+
constructor() {
|
|
391
|
+
// Initialize layer after DOM is ready
|
|
392
|
+
afterNextRender(() => {
|
|
393
|
+
this.layerService.addLayer({
|
|
394
|
+
id: this.id(),
|
|
395
|
+
type: 'tile',
|
|
396
|
+
source: {
|
|
397
|
+
type: this.source(),
|
|
398
|
+
url: this.url(),
|
|
399
|
+
attributions: this.attributions(),
|
|
400
|
+
params: this.params(),
|
|
401
|
+
},
|
|
402
|
+
zIndex: this.zIndex(),
|
|
403
|
+
opacity: this.opacity(),
|
|
404
|
+
visible: this.visible(),
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
// Cleanup when component is destroyed
|
|
408
|
+
this.destroyRef.onDestroy(() => {
|
|
409
|
+
this.layerService.removeLayer(this.id());
|
|
177
410
|
});
|
|
178
|
-
// If layer wasn't added (map not ready), retry with exponential backoff
|
|
179
|
-
if (retryCount < 10) {
|
|
180
|
-
setTimeout(() => {
|
|
181
|
-
// Check if layer was actually added by trying again
|
|
182
|
-
this.tryAddLayer(retryCount + 1);
|
|
183
|
-
}, Math.min(50 * (retryCount + 1), 500));
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
ngOnDestroy() {
|
|
187
|
-
this.layerService.removeLayer(this.id());
|
|
188
411
|
}
|
|
189
412
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: OlTileLayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
190
413
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: OlTileLayerComponent, isStandalone: true, selector: "ol-tile-layer", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: true, transformFunction: null }, url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null }, attributions: { classPropertyName: "attributions", publicName: "attributions", isSignal: true, isRequired: false, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, opacity: { classPropertyName: "opacity", publicName: "opacity", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -196,7 +419,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
196
419
|
template: '',
|
|
197
420
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
198
421
|
}]
|
|
199
|
-
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: true }] }], url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }], attributions: [{ type: i0.Input, args: [{ isSignal: true, alias: "attributions", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }] } });
|
|
422
|
+
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: true }] }], url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }], attributions: [{ type: i0.Input, args: [{ isSignal: true, alias: "attributions", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }] } });
|
|
423
|
+
|
|
424
|
+
// OlImageLayerComponent
|
|
425
|
+
class OlImageLayerComponent {
|
|
426
|
+
layerService = inject(OlLayerService);
|
|
427
|
+
destroyRef = inject(DestroyRef);
|
|
428
|
+
id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
429
|
+
sourceType = input.required(...(ngDevMode ? [{ debugName: "sourceType" }] : /* istanbul ignore next */ []));
|
|
430
|
+
url = input.required(...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
|
|
431
|
+
params = input(...(ngDevMode ? [undefined, { debugName: "params" }] : /* istanbul ignore next */ []));
|
|
432
|
+
imageExtent = input(...(ngDevMode ? [undefined, { debugName: "imageExtent" }] : /* istanbul ignore next */ []));
|
|
433
|
+
zIndex = input(0, ...(ngDevMode ? [{ debugName: "zIndex" }] : /* istanbul ignore next */ []));
|
|
434
|
+
opacity = input(1, ...(ngDevMode ? [{ debugName: "opacity" }] : /* istanbul ignore next */ []));
|
|
435
|
+
visible = input(true, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
436
|
+
constructor() {
|
|
437
|
+
// Initialize layer after DOM is ready
|
|
438
|
+
afterNextRender(() => {
|
|
439
|
+
this.layerService.addLayer({
|
|
440
|
+
id: this.id(),
|
|
441
|
+
type: 'image',
|
|
442
|
+
source: {
|
|
443
|
+
type: this.sourceType(),
|
|
444
|
+
url: this.url(),
|
|
445
|
+
params: this.params(),
|
|
446
|
+
imageExtent: this.imageExtent(),
|
|
447
|
+
},
|
|
448
|
+
zIndex: this.zIndex(),
|
|
449
|
+
opacity: this.opacity(),
|
|
450
|
+
visible: this.visible(),
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
// Cleanup when component is destroyed
|
|
454
|
+
this.destroyRef.onDestroy(() => {
|
|
455
|
+
this.layerService.removeLayer(this.id());
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: OlImageLayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
459
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: OlImageLayerComponent, isStandalone: true, selector: "ol-image-layer", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, sourceType: { classPropertyName: "sourceType", publicName: "sourceType", isSignal: true, isRequired: true, transformFunction: null }, url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: true, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null }, imageExtent: { classPropertyName: "imageExtent", publicName: "imageExtent", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, opacity: { classPropertyName: "opacity", publicName: "opacity", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
460
|
+
}
|
|
461
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: OlImageLayerComponent, decorators: [{
|
|
462
|
+
type: Component,
|
|
463
|
+
args: [{
|
|
464
|
+
selector: 'ol-image-layer',
|
|
465
|
+
template: '',
|
|
466
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
467
|
+
}]
|
|
468
|
+
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], sourceType: [{ type: i0.Input, args: [{ isSignal: true, alias: "sourceType", required: true }] }], url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: true }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], imageExtent: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageExtent", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }] } });
|
|
200
469
|
|
|
201
470
|
// Provider functions
|
|
202
471
|
function withLayers() {
|
|
@@ -212,4 +481,4 @@ function provideLayers() {
|
|
|
212
481
|
* Generated bundle index. Do not edit.
|
|
213
482
|
*/
|
|
214
483
|
|
|
215
|
-
export { OlLayerService, OlTileLayerComponent, OlVectorLayerComponent, provideLayers, withLayers };
|
|
484
|
+
export { OlImageLayerComponent, OlLayerService, OlTileLayerComponent, OlVectorLayerComponent, provideLayers, withLayers };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-helpers/openlayers",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Modern Angular wrapper for OpenLayers with modular architecture, standalone components, and hybrid template/programmatic API",
|
|
5
5
|
"homepage": "https://gaspar1992.github.io/angular-helpers/docs/openlayers",
|
|
6
6
|
"repository": {
|
|
@@ -74,6 +74,7 @@
|
|
|
74
74
|
"default": "./fesm2022/angular-helpers-openlayers-overlays.mjs"
|
|
75
75
|
}
|
|
76
76
|
},
|
|
77
|
+
"type": "module",
|
|
77
78
|
"dependencies": {
|
|
78
79
|
"tslib": "^2.3.0"
|
|
79
80
|
}
|