@angular-helpers/openlayers 0.7.0 → 21.14.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.
- package/fesm2022/angular-helpers-openlayers-controls.mjs +9 -11
- package/fesm2022/angular-helpers-openlayers-interactions.mjs +0 -3
- package/fesm2022/angular-helpers-openlayers-layers.mjs +59 -13
- package/fesm2022/angular-helpers-openlayers-testing.mjs +15 -0
- package/package.json +6 -1
- package/types/angular-helpers-openlayers-controls.d.ts +1 -1
- package/types/angular-helpers-openlayers-core.d.ts +2 -2
- package/types/angular-helpers-openlayers-interactions.d.ts +11 -11
- package/types/angular-helpers-openlayers-layers.d.ts +17 -15
- package/types/angular-helpers-openlayers-overlays.d.ts +2 -2
- package/types/angular-helpers-openlayers-testing.d.ts +5 -0
|
@@ -6,8 +6,6 @@ import Attribution from 'ol/control/Attribution';
|
|
|
6
6
|
import ScaleLine from 'ol/control/ScaleLine';
|
|
7
7
|
import FullScreen from 'ol/control/FullScreen';
|
|
8
8
|
import Rotate from 'ol/control/Rotate';
|
|
9
|
-
import * as i1 from '@angular/common';
|
|
10
|
-
import { CommonModule } from '@angular/common';
|
|
11
9
|
import Control from 'ol/control/Control';
|
|
12
10
|
import Geolocation from 'ol/Geolocation';
|
|
13
11
|
import Feature from 'ol/Feature';
|
|
@@ -383,11 +381,11 @@ class OlLayerSwitcherComponent {
|
|
|
383
381
|
</div>
|
|
384
382
|
}
|
|
385
383
|
</div>
|
|
386
|
-
`, isInline: true, styles: [":host{display:block}.ol-layer-switcher{position:absolute;background:#fffffff2;color:#333;border-radius:4px;border:none;box-shadow:0 1px 4px #0000004d;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:13px;min-width:36px;z-index:10;transition:all .2s ease}.ol-layer-switcher--top-left{top:.5em;left:.5em}.ol-layer-switcher--top-right{top:10em;right:.5em}.ol-layer-switcher--bottom-left{bottom:.5em;left:.5em}.ol-layer-switcher--bottom-right{bottom:.5em;right:.5em}.ol-layer-switcher.collapsed{min-width:auto}.ol-layer-switcher__toggle{display:flex;align-items:center;gap:6px;padding:4px 8px;background:transparent;color:#333;border:none;border-bottom:1px solid rgba(0,0,0,.08);border-radius:4px 4px 0 0;cursor:pointer;width:100%;font-size:13px;font-weight:600;transition:background .15s ease;min-height:36px}.ol-layer-switcher.collapsed .ol-layer-switcher__toggle{border-bottom:none;border-radius:4px;padding:4px 6px;justify-content:center}.ol-layer-switcher__toggle:hover{background:#0000000d}.ol-layer-switcher__icon{font-size:14px;line-height:1}.ol-layer-switcher__title{font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.5px}.ol-layer-switcher.collapsed .ol-layer-switcher__title,.ol-layer-switcher.collapsed .ol-layer-switcher__panel{display:none}.ol-layer-switcher__panel{padding:6px;max-height:300px;overflow-y:auto}.ol-layer-switcher__empty{padding:12px;color:#6b7280;text-align:center;font-style:italic;font-size:12px}.ol-layer-switcher__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}.ol-layer-switcher__item{padding:5px 8px;border-radius:3px;transition:background .15s ease}.ol-layer-switcher__item:hover{background:#0000000a}.ol-layer-switcher__label{display:flex;align-items:center;gap:6px;cursor:pointer;font-size:12px}.ol-layer-switcher__checkbox{cursor:pointer;accent-color:#1a73e8}.ol-layer-switcher__name{flex:1;font-weight:500;color:#333;font-size:12px}.ol-layer-switcher__type{font-size:9px;padding:2px 5px;border-radius:3px;font-weight:700;text-transform:uppercase;background:#0000000f;color:#555;letter-spacing:.3px}.ol-layer-switcher__type--vector{background:#3b82f61f;color:#2563eb}.ol-layer-switcher__type--tile{background:#22c55e1f;color:#16a34a}.ol-layer-switcher__type--image{background:#f59e0b1f;color:#d97706}.ol-layer-switcher__opacity{width:100%;margin-top:4px;cursor:pointer;height:4px;accent-color:#1a73e8}\n"],
|
|
384
|
+
`, isInline: true, styles: [":host{display:block}.ol-layer-switcher{position:absolute;background:#fffffff2;color:#333;border-radius:4px;border:none;box-shadow:0 1px 4px #0000004d;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:13px;min-width:36px;z-index:10;transition:all .2s ease}.ol-layer-switcher--top-left{top:.5em;left:.5em}.ol-layer-switcher--top-right{top:10em;right:.5em}.ol-layer-switcher--bottom-left{bottom:.5em;left:.5em}.ol-layer-switcher--bottom-right{bottom:.5em;right:.5em}.ol-layer-switcher.collapsed{min-width:auto}.ol-layer-switcher__toggle{display:flex;align-items:center;gap:6px;padding:4px 8px;background:transparent;color:#333;border:none;border-bottom:1px solid rgba(0,0,0,.08);border-radius:4px 4px 0 0;cursor:pointer;width:100%;font-size:13px;font-weight:600;transition:background .15s ease;min-height:36px}.ol-layer-switcher.collapsed .ol-layer-switcher__toggle{border-bottom:none;border-radius:4px;padding:4px 6px;justify-content:center}.ol-layer-switcher__toggle:hover{background:#0000000d}.ol-layer-switcher__icon{font-size:14px;line-height:1}.ol-layer-switcher__title{font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.5px}.ol-layer-switcher.collapsed .ol-layer-switcher__title,.ol-layer-switcher.collapsed .ol-layer-switcher__panel{display:none}.ol-layer-switcher__panel{padding:6px;max-height:300px;overflow-y:auto}.ol-layer-switcher__empty{padding:12px;color:#6b7280;text-align:center;font-style:italic;font-size:12px}.ol-layer-switcher__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}.ol-layer-switcher__item{padding:5px 8px;border-radius:3px;transition:background .15s ease}.ol-layer-switcher__item:hover{background:#0000000a}.ol-layer-switcher__label{display:flex;align-items:center;gap:6px;cursor:pointer;font-size:12px}.ol-layer-switcher__checkbox{cursor:pointer;accent-color:#1a73e8}.ol-layer-switcher__name{flex:1;font-weight:500;color:#333;font-size:12px}.ol-layer-switcher__type{font-size:9px;padding:2px 5px;border-radius:3px;font-weight:700;text-transform:uppercase;background:#0000000f;color:#555;letter-spacing:.3px}.ol-layer-switcher__type--vector{background:#3b82f61f;color:#2563eb}.ol-layer-switcher__type--tile{background:#22c55e1f;color:#16a34a}.ol-layer-switcher__type--image{background:#f59e0b1f;color:#d97706}.ol-layer-switcher__opacity{width:100%;margin-top:4px;cursor:pointer;height:4px;accent-color:#1a73e8}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
387
385
|
}
|
|
388
386
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlLayerSwitcherComponent, decorators: [{
|
|
389
387
|
type: Component,
|
|
390
|
-
args: [{ selector: 'ol-layer-switcher',
|
|
388
|
+
args: [{ selector: 'ol-layer-switcher', changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
391
389
|
<div
|
|
392
390
|
class="ol-layer-switcher"
|
|
393
391
|
[class.collapsed]="isCollapsed()"
|
|
@@ -578,11 +576,11 @@ class OlBasemapSwitcherComponent {
|
|
|
578
576
|
</span>
|
|
579
577
|
</button>
|
|
580
578
|
</div>
|
|
581
|
-
`, isInline: true, styles: [":host{display:block}.ol-basemap-switcher{position:absolute;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:13px;color:#333;z-index:10}.ol-basemap-switcher--top-left{top:.5em;left:.5em}.ol-basemap-switcher--top-center{top:.5em;left:50%;transform:translate(-50%)}.ol-basemap-switcher--top-right{top:.5em;right:.5em}.ol-basemap-switcher--bottom-left{bottom:.5em;left:.5em}.ol-basemap-switcher--bottom-center{bottom:.5em;left:50%;transform:translate(-50%)}.ol-basemap-switcher--bottom-right{bottom:.5em;right:.5em}.ol-basemap-switcher__toggle{display:flex;align-items:center;gap:6px;padding:4px 10px;background:#fffffff2;color:#333;border:none;border-radius:4px;box-shadow:0 1px 4px #0000004d;cursor:pointer;font-size:12px;font-weight:600;transition:background .15s ease;min-height:36px}.ol-basemap-switcher__toggle:hover{background:#fff}.ol-basemap-switcher__toggle-icon{font-size:14px;line-height:1}.ol-basemap-switcher__toggle-text{font-weight:600;font-size:12px}.ol-basemap-switcher__panel{position:absolute;bottom:calc(100% + 6px);left:0;background:#fffffff2;border:none;color:#333;border-radius:4px;box-shadow:0 1px 4px #0000004d;padding:4px;min-width:160px;display:flex;flex-direction:column;gap:2px}.ol-basemap-switcher--bottom-right .ol-basemap-switcher__panel,.ol-basemap-switcher--top-right .ol-basemap-switcher__panel{left:auto;right:0}.ol-basemap-switcher--top-left .ol-basemap-switcher__panel,.ol-basemap-switcher--top-center .ol-basemap-switcher__panel,.ol-basemap-switcher--top-right .ol-basemap-switcher__panel{bottom:auto;top:calc(100% + 6px)}.ol-basemap-switcher--top-center .ol-basemap-switcher__panel,.ol-basemap-switcher--bottom-center .ol-basemap-switcher__panel{left:50%;transform:translate(-50%)}.ol-basemap-switcher__item{display:flex;align-items:center;gap:8px;width:100%;padding:6px 10px;border:none;background:transparent;border-radius:3px;cursor:pointer;text-align:left;font-size:12px;transition:background .15s ease}.ol-basemap-switcher__item:hover{background:#0000000d}.ol-basemap-switcher__item--active{background:#1a73e81f;color:#1a73e8;font-weight:600}.ol-basemap-switcher__item--active:hover{background:#1a73e82e}.ol-basemap-switcher__icon{font-size:14px}.ol-basemap-switcher__name{font-weight:500;color:#333;font-size:12px}\n"],
|
|
579
|
+
`, isInline: true, styles: [":host{display:block}.ol-basemap-switcher{position:absolute;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:13px;color:#333;z-index:10}.ol-basemap-switcher--top-left{top:.5em;left:.5em}.ol-basemap-switcher--top-center{top:.5em;left:50%;transform:translate(-50%)}.ol-basemap-switcher--top-right{top:.5em;right:.5em}.ol-basemap-switcher--bottom-left{bottom:.5em;left:.5em}.ol-basemap-switcher--bottom-center{bottom:.5em;left:50%;transform:translate(-50%)}.ol-basemap-switcher--bottom-right{bottom:.5em;right:.5em}.ol-basemap-switcher__toggle{display:flex;align-items:center;gap:6px;padding:4px 10px;background:#fffffff2;color:#333;border:none;border-radius:4px;box-shadow:0 1px 4px #0000004d;cursor:pointer;font-size:12px;font-weight:600;transition:background .15s ease;min-height:36px}.ol-basemap-switcher__toggle:hover{background:#fff}.ol-basemap-switcher__toggle-icon{font-size:14px;line-height:1}.ol-basemap-switcher__toggle-text{font-weight:600;font-size:12px}.ol-basemap-switcher__panel{position:absolute;bottom:calc(100% + 6px);left:0;background:#fffffff2;border:none;color:#333;border-radius:4px;box-shadow:0 1px 4px #0000004d;padding:4px;min-width:160px;display:flex;flex-direction:column;gap:2px}.ol-basemap-switcher--bottom-right .ol-basemap-switcher__panel,.ol-basemap-switcher--top-right .ol-basemap-switcher__panel{left:auto;right:0}.ol-basemap-switcher--top-left .ol-basemap-switcher__panel,.ol-basemap-switcher--top-center .ol-basemap-switcher__panel,.ol-basemap-switcher--top-right .ol-basemap-switcher__panel{bottom:auto;top:calc(100% + 6px)}.ol-basemap-switcher--top-center .ol-basemap-switcher__panel,.ol-basemap-switcher--bottom-center .ol-basemap-switcher__panel{left:50%;transform:translate(-50%)}.ol-basemap-switcher__item{display:flex;align-items:center;gap:8px;width:100%;padding:6px 10px;border:none;background:transparent;border-radius:3px;cursor:pointer;text-align:left;font-size:12px;transition:background .15s ease}.ol-basemap-switcher__item:hover{background:#0000000d}.ol-basemap-switcher__item--active{background:#1a73e81f;color:#1a73e8;font-weight:600}.ol-basemap-switcher__item--active:hover{background:#1a73e82e}.ol-basemap-switcher__icon{font-size:14px}.ol-basemap-switcher__name{font-weight:500;color:#333;font-size:12px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
582
580
|
}
|
|
583
581
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlBasemapSwitcherComponent, decorators: [{
|
|
584
582
|
type: Component,
|
|
585
|
-
args: [{ selector: 'ol-basemap-switcher',
|
|
583
|
+
args: [{ selector: 'ol-basemap-switcher', changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
586
584
|
<div
|
|
587
585
|
class="ol-basemap-switcher"
|
|
588
586
|
[class.ol-basemap-switcher--top-left]="position() === 'top-left'"
|
|
@@ -753,7 +751,7 @@ class OlGeolocationControlComponent {
|
|
|
753
751
|
<div
|
|
754
752
|
#controlElement
|
|
755
753
|
class="ol-geolocation-control ol-unselectable ol-control"
|
|
756
|
-
[
|
|
754
|
+
[class]="position()"
|
|
757
755
|
>
|
|
758
756
|
<button
|
|
759
757
|
type="button"
|
|
@@ -780,15 +778,15 @@ class OlGeolocationControlComponent {
|
|
|
780
778
|
</svg>
|
|
781
779
|
</button>
|
|
782
780
|
</div>
|
|
783
|
-
`, isInline: true, styles: [".ol-geolocation-control{position:absolute}.ol-geolocation-control.top-left{top:4.5em;left:.5em}.ol-geolocation-control.top-right{top:4.5em;right:.5em}.ol-geolocation-control.bottom-left{bottom:.5em;left:.5em}.ol-geolocation-control.bottom-right{bottom:.5em;right:.5em}button{display:flex;align-items:center;justify-content:center;width:1.375em;height:1.375em;padding:0;background-color:#fff6;border:none;cursor:pointer;border-radius:2px;color:#333;transition:all .2s}button:hover{background-color:#fffc}button.active{color:#3b82f6;background-color:#ffffffe6}.geolocation-icon{width:1em;height:1em}\n"],
|
|
781
|
+
`, isInline: true, styles: [".ol-geolocation-control{position:absolute}.ol-geolocation-control.top-left{top:4.5em;left:.5em}.ol-geolocation-control.top-right{top:4.5em;right:.5em}.ol-geolocation-control.bottom-left{bottom:.5em;left:.5em}.ol-geolocation-control.bottom-right{bottom:.5em;right:.5em}button{display:flex;align-items:center;justify-content:center;width:1.375em;height:1.375em;padding:0;background-color:#fff6;border:none;cursor:pointer;border-radius:2px;color:#333;transition:all .2s}button:hover{background-color:#fffc}button.active{color:#3b82f6;background-color:#ffffffe6}.geolocation-icon{width:1em;height:1em}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
784
782
|
}
|
|
785
783
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlGeolocationControlComponent, decorators: [{
|
|
786
784
|
type: Component,
|
|
787
|
-
args: [{ selector: 'ol-geolocation-control',
|
|
785
|
+
args: [{ selector: 'ol-geolocation-control', changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
788
786
|
<div
|
|
789
787
|
#controlElement
|
|
790
788
|
class="ol-geolocation-control ol-unselectable ol-control"
|
|
791
|
-
[
|
|
789
|
+
[class]="position()"
|
|
792
790
|
>
|
|
793
791
|
<button
|
|
794
792
|
type="button"
|
|
@@ -1020,7 +1018,7 @@ class OlTimelineComponent {
|
|
|
1020
1018
|
}
|
|
1021
1019
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlTimelineComponent, decorators: [{
|
|
1022
1020
|
type: Component,
|
|
1023
|
-
args: [{ selector: 'ol-timeline',
|
|
1021
|
+
args: [{ selector: 'ol-timeline', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
1024
1022
|
<div
|
|
1025
1023
|
class="ol-timeline"
|
|
1026
1024
|
[class.ol-timeline--top-left]="position() === 'top-left'"
|
|
@@ -887,7 +887,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
|
|
|
887
887
|
type: Component,
|
|
888
888
|
args: [{
|
|
889
889
|
selector: 'ol-draw-interaction',
|
|
890
|
-
standalone: true,
|
|
891
890
|
template: '',
|
|
892
891
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
893
892
|
}]
|
|
@@ -928,7 +927,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
|
|
|
928
927
|
type: Component,
|
|
929
928
|
args: [{
|
|
930
929
|
selector: 'ol-modify-interaction',
|
|
931
|
-
standalone: true,
|
|
932
930
|
template: '',
|
|
933
931
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
934
932
|
}]
|
|
@@ -973,7 +971,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImpo
|
|
|
973
971
|
type: Component,
|
|
974
972
|
args: [{
|
|
975
973
|
selector: 'ol-select-interaction',
|
|
976
|
-
standalone: true,
|
|
977
974
|
template: '',
|
|
978
975
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
979
976
|
}]
|
|
@@ -161,7 +161,7 @@ function buildVectorLayer(config, source) {
|
|
|
161
161
|
visible: config.visible ?? true,
|
|
162
162
|
opacity: config.opacity ?? 1,
|
|
163
163
|
zIndex: config.zIndex,
|
|
164
|
-
style: clusterCfg?.enabled ? clusterStyleFn : styleFn,
|
|
164
|
+
style: (clusterCfg?.enabled ? clusterStyleFn : styleFn),
|
|
165
165
|
});
|
|
166
166
|
layer.set('id', config.id);
|
|
167
167
|
layer.set('cluster-config', clusterCfg);
|
|
@@ -377,22 +377,25 @@ class OlLayerService {
|
|
|
377
377
|
}
|
|
378
378
|
}
|
|
379
379
|
}
|
|
380
|
+
createVectorSource(config, map) {
|
|
381
|
+
const sourceOptions = {};
|
|
382
|
+
if (config.url && config.format) {
|
|
383
|
+
sourceOptions.url = config.url;
|
|
384
|
+
if (config.format === 'geojson')
|
|
385
|
+
sourceOptions.format = new GeoJSON();
|
|
386
|
+
else if (config.format === 'topojson')
|
|
387
|
+
sourceOptions.format = new TopoJSON();
|
|
388
|
+
else if (config.format === 'kml')
|
|
389
|
+
sourceOptions.format = new KML();
|
|
390
|
+
}
|
|
391
|
+
return new VectorSource(sourceOptions);
|
|
392
|
+
}
|
|
380
393
|
createLayer(config, map) {
|
|
381
394
|
let layer;
|
|
382
395
|
switch (config.type) {
|
|
383
396
|
case 'vector': {
|
|
384
397
|
const vConfig = config;
|
|
385
|
-
const
|
|
386
|
-
if (vConfig.url && vConfig.format) {
|
|
387
|
-
sourceOptions.url = vConfig.url;
|
|
388
|
-
if (vConfig.format === 'geojson')
|
|
389
|
-
sourceOptions.format = new GeoJSON();
|
|
390
|
-
else if (vConfig.format === 'topojson')
|
|
391
|
-
sourceOptions.format = new TopoJSON();
|
|
392
|
-
else if (vConfig.format === 'kml')
|
|
393
|
-
sourceOptions.format = new KML();
|
|
394
|
-
}
|
|
395
|
-
const vectorSource = new VectorSource(sourceOptions);
|
|
398
|
+
const vectorSource = this.createVectorSource(vConfig, map);
|
|
396
399
|
const targetProj = (typeof map.getView === 'function'
|
|
397
400
|
? map.getView()?.getProjection()?.getCode()
|
|
398
401
|
: undefined) ?? 'EPSG:3857';
|
|
@@ -497,6 +500,41 @@ class OlLayerService {
|
|
|
497
500
|
this.updateLayerState();
|
|
498
501
|
}
|
|
499
502
|
}
|
|
503
|
+
updateVectorLayerConfig(id, config) {
|
|
504
|
+
const layer = this.layerCache.get(id);
|
|
505
|
+
if (!(layer instanceof VectorLayer))
|
|
506
|
+
return;
|
|
507
|
+
const map = this.mapService.getMap();
|
|
508
|
+
const nextConfig = {
|
|
509
|
+
...(layer.get('cluster-config') ? { cluster: layer.get('cluster-config') } : {}),
|
|
510
|
+
...(layer.get('style-fn') !== undefined ? { style: layer.get('style-fn') } : {}),
|
|
511
|
+
...config,
|
|
512
|
+
};
|
|
513
|
+
const nextSource = this.createVectorSource(nextConfig, map ?? {});
|
|
514
|
+
const clusterCfg = nextConfig.cluster;
|
|
515
|
+
if (clusterCfg?.enabled) {
|
|
516
|
+
const clusterSource = new ClusterSource({
|
|
517
|
+
source: nextSource,
|
|
518
|
+
distance: clusterCfg.distance ?? 40,
|
|
519
|
+
minDistance: clusterCfg.minDistance ?? 20,
|
|
520
|
+
geometryFunction: (feature) => {
|
|
521
|
+
const geometry = feature.getGeometry();
|
|
522
|
+
if (!geometry)
|
|
523
|
+
return null;
|
|
524
|
+
if (geometry.getType() === 'Point')
|
|
525
|
+
return geometry;
|
|
526
|
+
return new Point(getCenter(geometry.getExtent()));
|
|
527
|
+
},
|
|
528
|
+
});
|
|
529
|
+
layer.setSource(clusterSource);
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
layer.setSource(nextSource);
|
|
533
|
+
}
|
|
534
|
+
layer.set('coordinate-projection', nextConfig.coordinateProjection ?? 'EPSG:4326');
|
|
535
|
+
this.updateFeatures(id, nextConfig.features ?? []);
|
|
536
|
+
this.updateLayerState();
|
|
537
|
+
}
|
|
500
538
|
setVisibility(id, visible) {
|
|
501
539
|
const layer = this.layerCache.get(id);
|
|
502
540
|
if (layer) {
|
|
@@ -746,11 +784,19 @@ class OlVectorLayerComponent {
|
|
|
746
784
|
// Effect to sync features when input changes
|
|
747
785
|
effect(() => {
|
|
748
786
|
const currentFeatures = this.features();
|
|
749
|
-
// Only update if layer already exists (afterNextRender already created it)
|
|
750
787
|
if (this.layerService.getLayer(this.id())) {
|
|
751
788
|
this.layerService.updateFeatures(this.id(), currentFeatures);
|
|
752
789
|
}
|
|
753
790
|
});
|
|
791
|
+
effect(() => {
|
|
792
|
+
if (this.layerService.getLayer(this.id())) {
|
|
793
|
+
this.layerService.updateVectorLayerConfig(this.id(), {
|
|
794
|
+
url: this.url(),
|
|
795
|
+
format: this.format(),
|
|
796
|
+
coordinateProjection: this.coordinateProjection(),
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
});
|
|
754
800
|
effect(() => {
|
|
755
801
|
this.layerService.setOpacity(this.id(), this.opacity());
|
|
756
802
|
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { MockComponent } from '@angular-helpers/testing';
|
|
2
|
+
|
|
3
|
+
// This provides a pre-configured mock for the complex OlMapComponent,
|
|
4
|
+
// avoiding the need to mock openlayers library internals or deal with ResizeObservers.
|
|
5
|
+
const MockOlMapComponent = MockComponent({
|
|
6
|
+
selector: 'ol-map',
|
|
7
|
+
inputs: ['center', 'zoom', 'rotation', 'projection', 'coordinateProjection'],
|
|
8
|
+
outputs: ['viewChange', 'mapClick', 'mapDblClick'],
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generated bundle index. Do not edit.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export { MockOlMapComponent };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-helpers/openlayers",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "21.14.1",
|
|
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": {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
+
"@angular-helpers/testing": "^21.14.0",
|
|
33
34
|
"@angular/common": "^21.0.0",
|
|
34
35
|
"@angular/core": "^21.0.0",
|
|
35
36
|
"milsymbol": "^3.0.0",
|
|
@@ -76,6 +77,10 @@
|
|
|
76
77
|
"./overlays": {
|
|
77
78
|
"types": "./types/angular-helpers-openlayers-overlays.d.ts",
|
|
78
79
|
"default": "./fesm2022/angular-helpers-openlayers-overlays.mjs"
|
|
80
|
+
},
|
|
81
|
+
"./testing": {
|
|
82
|
+
"types": "./types/angular-helpers-openlayers-testing.d.ts",
|
|
83
|
+
"default": "./fesm2022/angular-helpers-openlayers-testing.mjs"
|
|
79
84
|
}
|
|
80
85
|
},
|
|
81
86
|
"type": "module",
|
|
@@ -40,7 +40,7 @@ declare class OlScaleLineControlComponent {
|
|
|
40
40
|
declare class OlFullscreenControlComponent {
|
|
41
41
|
private mapService;
|
|
42
42
|
private zoneHelper;
|
|
43
|
-
source: _angular_core.InputSignal<HTMLElement>;
|
|
43
|
+
source: _angular_core.InputSignal<HTMLElement | undefined>;
|
|
44
44
|
label: _angular_core.InputSignal<string>;
|
|
45
45
|
labelActive: _angular_core.InputSignal<string>;
|
|
46
46
|
tipLabel: _angular_core.InputSignal<string>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { ElementRef, Signal,
|
|
2
|
+
import { ElementRef, Signal, ResourceRef, Provider, EnvironmentProviders } from '@angular/core';
|
|
3
3
|
import OLMap from 'ol/Map';
|
|
4
4
|
import { View, Feature as Feature$1 } from 'ol';
|
|
5
5
|
|
|
@@ -380,7 +380,7 @@ interface VectorResourceOptions {
|
|
|
380
380
|
* @param options Additional vector resource options
|
|
381
381
|
* @returns An Angular Resource containing an array of parsed Features
|
|
382
382
|
*/
|
|
383
|
-
declare function createVectorResource(url: Signal<string | undefined>, options?: VectorResourceOptions):
|
|
383
|
+
declare function createVectorResource(url: Signal<string | undefined>, options?: VectorResourceOptions): ResourceRef<Feature[] | undefined>;
|
|
384
384
|
|
|
385
385
|
interface ProjectionOptions {
|
|
386
386
|
sourceProjection?: string;
|
|
@@ -87,7 +87,7 @@ declare class OlInteractionService {
|
|
|
87
87
|
private drawService;
|
|
88
88
|
private modifyService;
|
|
89
89
|
readonly selectedFeatures: _angular_core.Signal<Feature[]>;
|
|
90
|
-
readonly hoveredFeature: _angular_core.Signal<Feature>;
|
|
90
|
+
readonly hoveredFeature: _angular_core.Signal<Feature | null>;
|
|
91
91
|
readonly selectionCount: _angular_core.Signal<number>;
|
|
92
92
|
readonly hasSelection: _angular_core.Signal<boolean>;
|
|
93
93
|
readonly activeInteractions: _angular_core.Signal<_angular_helpers_openlayers_interactions.ManagedInteraction[]>;
|
|
@@ -183,7 +183,7 @@ declare class InteractionStateService {
|
|
|
183
183
|
private modifySubject;
|
|
184
184
|
private selectSubject;
|
|
185
185
|
readonly selectedFeatures: _angular_core.Signal<Feature[]>;
|
|
186
|
-
readonly hoveredFeature: _angular_core.Signal<Feature>;
|
|
186
|
+
readonly hoveredFeature: _angular_core.Signal<Feature | null>;
|
|
187
187
|
readonly selectionCount: _angular_core.Signal<number>;
|
|
188
188
|
readonly hasSelection: _angular_core.Signal<boolean>;
|
|
189
189
|
readonly activeInteractions: _angular_core.Signal<ManagedInteraction[]>;
|
|
@@ -354,9 +354,9 @@ declare class OlDrawInteractionComponent {
|
|
|
354
354
|
private destroyRef;
|
|
355
355
|
id: _angular_core.InputSignal<string>;
|
|
356
356
|
type: _angular_core.InputSignal<"Point" | "LineString" | "Polygon" | "Circle">;
|
|
357
|
-
source: _angular_core.InputSignal<string>;
|
|
358
|
-
freehand: _angular_core.InputSignal<boolean>;
|
|
359
|
-
snapTolerance: _angular_core.InputSignal<number>;
|
|
357
|
+
source: _angular_core.InputSignal<string | undefined>;
|
|
358
|
+
freehand: _angular_core.InputSignal<boolean | undefined>;
|
|
359
|
+
snapTolerance: _angular_core.InputSignal<number | undefined>;
|
|
360
360
|
active: _angular_core.InputSignal<boolean>;
|
|
361
361
|
private drawStartFiltered$;
|
|
362
362
|
private drawEndFiltered$;
|
|
@@ -374,8 +374,8 @@ declare class OlModifyInteractionComponent {
|
|
|
374
374
|
private interactionService;
|
|
375
375
|
private destroyRef;
|
|
376
376
|
id: _angular_core.InputSignal<string>;
|
|
377
|
-
source: _angular_core.InputSignal<string>;
|
|
378
|
-
snapTolerance: _angular_core.InputSignal<number>;
|
|
377
|
+
source: _angular_core.InputSignal<string | undefined>;
|
|
378
|
+
snapTolerance: _angular_core.InputSignal<number | undefined>;
|
|
379
379
|
active: _angular_core.InputSignal<boolean>;
|
|
380
380
|
private modifyFiltered$;
|
|
381
381
|
modifyEvent: _angular_core.OutputRef<_angular_helpers_openlayers_interactions.ModifyEvent>;
|
|
@@ -391,10 +391,10 @@ declare class OlSelectInteractionComponent {
|
|
|
391
391
|
private interactionService;
|
|
392
392
|
private destroyRef;
|
|
393
393
|
id: _angular_core.InputSignal<string>;
|
|
394
|
-
layers: _angular_core.InputSignal<string[]>;
|
|
395
|
-
multi: _angular_core.InputSignal<boolean>;
|
|
396
|
-
hitTolerance: _angular_core.InputSignal<number>;
|
|
397
|
-
condition: _angular_core.InputSignal<"click" | "pointerMove">;
|
|
394
|
+
layers: _angular_core.InputSignal<string[] | undefined>;
|
|
395
|
+
multi: _angular_core.InputSignal<boolean | undefined>;
|
|
396
|
+
hitTolerance: _angular_core.InputSignal<number | undefined>;
|
|
397
|
+
condition: _angular_core.InputSignal<"click" | "pointerMove" | undefined>;
|
|
398
398
|
active: _angular_core.InputSignal<boolean>;
|
|
399
399
|
private selectFiltered$;
|
|
400
400
|
selectEvent: _angular_core.OutputRef<_angular_helpers_openlayers_interactions.SelectEvent>;
|
|
@@ -68,7 +68,7 @@ declare class OlClusterComponent {
|
|
|
68
68
|
distance: _angular_core.InputSignal<number>;
|
|
69
69
|
minDistance: _angular_core.InputSignal<number>;
|
|
70
70
|
showCount: _angular_core.InputSignal<boolean>;
|
|
71
|
-
featureStyle: _angular_core.InputSignal<Style>;
|
|
71
|
+
featureStyle: _angular_core.InputSignal<Style | undefined>;
|
|
72
72
|
spiderfyOnSelect: _angular_core.InputSignal<boolean>;
|
|
73
73
|
spiderfyClick: _angular_core.OutputEmitterRef<Feature>;
|
|
74
74
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<OlClusterComponent, never>;
|
|
@@ -80,14 +80,14 @@ declare class OlVectorLayerComponent {
|
|
|
80
80
|
private destroyRef;
|
|
81
81
|
id: _angular_core.InputSignal<string>;
|
|
82
82
|
features: _angular_core.InputSignal<Feature[]>;
|
|
83
|
-
url: _angular_core.InputSignal<string>;
|
|
84
|
-
format: _angular_core.InputSignal<"geojson" | "topojson" | "kml">;
|
|
83
|
+
url: _angular_core.InputSignal<string | undefined>;
|
|
84
|
+
format: _angular_core.InputSignal<"geojson" | "topojson" | "kml" | undefined>;
|
|
85
85
|
zIndex: _angular_core.InputSignal<number>;
|
|
86
86
|
opacity: _angular_core.InputSignal<number>;
|
|
87
87
|
visible: _angular_core.InputSignal<boolean>;
|
|
88
88
|
style: _angular_core.InputSignal<any>;
|
|
89
|
-
cluster: _angular_core.InputSignal<ClusterConfig>;
|
|
90
|
-
clusterComponent: _angular_core.Signal<OlClusterComponent>;
|
|
89
|
+
cluster: _angular_core.InputSignal<ClusterConfig | undefined>;
|
|
90
|
+
clusterComponent: _angular_core.Signal<OlClusterComponent | undefined>;
|
|
91
91
|
coordinateProjection: _angular_core.InputSignal<string>;
|
|
92
92
|
constructor();
|
|
93
93
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<OlVectorLayerComponent, never>;
|
|
@@ -99,9 +99,9 @@ declare class OlTileLayerComponent {
|
|
|
99
99
|
private destroyRef;
|
|
100
100
|
id: _angular_core.InputSignal<string>;
|
|
101
101
|
source: _angular_core.InputSignal<"osm" | "xyz" | "wms">;
|
|
102
|
-
url: _angular_core.InputSignal<string>;
|
|
103
|
-
attributions: _angular_core.InputSignal<string | string[]>;
|
|
104
|
-
params: _angular_core.InputSignal<Record<string, unknown
|
|
102
|
+
url: _angular_core.InputSignal<string | undefined>;
|
|
103
|
+
attributions: _angular_core.InputSignal<string | string[] | undefined>;
|
|
104
|
+
params: _angular_core.InputSignal<Record<string, unknown> | undefined>;
|
|
105
105
|
zIndex: _angular_core.InputSignal<number>;
|
|
106
106
|
opacity: _angular_core.InputSignal<number>;
|
|
107
107
|
visible: _angular_core.InputSignal<boolean>;
|
|
@@ -116,8 +116,8 @@ declare class OlImageLayerComponent {
|
|
|
116
116
|
id: _angular_core.InputSignal<string>;
|
|
117
117
|
sourceType: _angular_core.InputSignal<"wms" | "static">;
|
|
118
118
|
url: _angular_core.InputSignal<string>;
|
|
119
|
-
params: _angular_core.InputSignal<Record<string, unknown
|
|
120
|
-
imageExtent: _angular_core.InputSignal<[number, number, number, number]>;
|
|
119
|
+
params: _angular_core.InputSignal<Record<string, unknown> | undefined>;
|
|
120
|
+
imageExtent: _angular_core.InputSignal<[number, number, number, number] | undefined>;
|
|
121
121
|
zIndex: _angular_core.InputSignal<number>;
|
|
122
122
|
opacity: _angular_core.InputSignal<number>;
|
|
123
123
|
visible: _angular_core.InputSignal<boolean>;
|
|
@@ -139,7 +139,7 @@ declare class OlHeatmapLayerComponent {
|
|
|
139
139
|
radius: _angular_core.InputSignal<number>;
|
|
140
140
|
/** Unit for radius and blur: 'pixels' (default) or 'meters' */
|
|
141
141
|
radiusUnit: _angular_core.InputSignal<"pixels" | "meters">;
|
|
142
|
-
weight: _angular_core.InputSignal<string | ((feature: Feature) => number)>;
|
|
142
|
+
weight: _angular_core.InputSignal<string | ((feature: Feature) => number) | undefined>;
|
|
143
143
|
/** Computed radius in pixels based on current resolution if unit is 'meters' */
|
|
144
144
|
private scaledRadius;
|
|
145
145
|
/** Computed blur in pixels based on current resolution if unit is 'meters' */
|
|
@@ -189,7 +189,7 @@ declare class OlWebGLVectorLayerComponent {
|
|
|
189
189
|
/** Disable hit detection for better performance (default: true) */
|
|
190
190
|
disableHitDetection: _angular_core.InputSignal<boolean>;
|
|
191
191
|
/** Style variables for dynamic expressions (e.g. `['var', 'threshold']`) */
|
|
192
|
-
variables: _angular_core.InputSignal<Record<string, string | number | boolean | number[]
|
|
192
|
+
variables: _angular_core.InputSignal<Record<string, string | number | boolean | number[]> | undefined>;
|
|
193
193
|
private layer;
|
|
194
194
|
private vectorSource;
|
|
195
195
|
constructor();
|
|
@@ -228,11 +228,11 @@ declare class OlWebGLTileLayerComponent {
|
|
|
228
228
|
/** Tile source type */
|
|
229
229
|
source: _angular_core.InputSignal<"osm" | "xyz" | "mvt">;
|
|
230
230
|
/** Tile URL template (required for 'xyz' and 'mvt') */
|
|
231
|
-
url: _angular_core.InputSignal<string>;
|
|
231
|
+
url: _angular_core.InputSignal<string | undefined>;
|
|
232
232
|
/** Attribution text */
|
|
233
|
-
attributions: _angular_core.InputSignal<string | string[]>;
|
|
233
|
+
attributions: _angular_core.InputSignal<string | string[] | undefined>;
|
|
234
234
|
/** WebGL tile style (raster expressions) or flat style (MVT) */
|
|
235
|
-
tileStyle: _angular_core.InputSignal<FlatStyleLike | Style$1>;
|
|
235
|
+
tileStyle: _angular_core.InputSignal<FlatStyleLike | Style$1 | undefined>;
|
|
236
236
|
/** Z-index for layer ordering */
|
|
237
237
|
zIndex: _angular_core.InputSignal<number>;
|
|
238
238
|
/** Opacity (0–1) */
|
|
@@ -268,10 +268,12 @@ declare class OlLayerService {
|
|
|
268
268
|
id: string;
|
|
269
269
|
};
|
|
270
270
|
private flushPending;
|
|
271
|
+
private createVectorSource;
|
|
271
272
|
private createLayer;
|
|
272
273
|
getLayer(id: string): BaseLayer | undefined;
|
|
273
274
|
hasLayer(id: string): boolean;
|
|
274
275
|
removeLayer(id: string): void;
|
|
276
|
+
updateVectorLayerConfig(id: string, config: Partial<VectorLayerConfig>): void;
|
|
275
277
|
setVisibility(id: string, visible: boolean): void;
|
|
276
278
|
toggleVisibility(id: string): boolean;
|
|
277
279
|
setOpacity(id: string, opacity: number): void;
|
|
@@ -99,7 +99,7 @@ declare class OlPopupComponent {
|
|
|
99
99
|
private readonly mapService;
|
|
100
100
|
private readonly zoneHelper;
|
|
101
101
|
/** Map coordinate where the popup is anchored. `null` hides the popup. */
|
|
102
|
-
readonly position: _angular_core.InputSignal<Coordinate>;
|
|
102
|
+
readonly position: _angular_core.InputSignal<Coordinate | null>;
|
|
103
103
|
/** Pixel offset relative to `position`. */
|
|
104
104
|
readonly offset: _angular_core.InputSignal<[number, number]>;
|
|
105
105
|
/** Anchor of the popup element relative to `position`. */
|
|
@@ -146,7 +146,7 @@ declare class OlTooltipDirective {
|
|
|
146
146
|
/** Property key to read from the hovered feature. */
|
|
147
147
|
readonly olTooltip: _angular_core.InputSignal<string>;
|
|
148
148
|
/** Optional layer id; when set, only features on that layer trigger the tooltip. */
|
|
149
|
-
readonly olTooltipLayer: _angular_core.InputSignal<string>;
|
|
149
|
+
readonly olTooltipLayer: _angular_core.InputSignal<string | null>;
|
|
150
150
|
private element;
|
|
151
151
|
private listener;
|
|
152
152
|
private currentMap;
|