@angular-helpers/openlayers 0.3.0 → 0.5.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/README.md +102 -6
- package/fesm2022/angular-helpers-openlayers-controls.mjs +289 -36
- package/fesm2022/angular-helpers-openlayers-core.mjs +215 -16
- package/fesm2022/angular-helpers-openlayers-interactions.mjs +426 -23
- package/fesm2022/angular-helpers-openlayers-layers.mjs +717 -38
- package/fesm2022/angular-helpers-openlayers-military.mjs +329 -12
- package/fesm2022/angular-helpers-openlayers-overlays.mjs +11 -10
- package/package.json +6 -2
- package/types/angular-helpers-openlayers-controls.d.ts +24 -4
- package/types/angular-helpers-openlayers-core.d.ts +143 -4
- package/types/angular-helpers-openlayers-interactions.d.ts +127 -23
- package/types/angular-helpers-openlayers-layers.d.ts +194 -35
- package/types/angular-helpers-openlayers-military.d.ts +160 -16
|
@@ -1,29 +1,346 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable } from '@angular/core';
|
|
2
|
+
import { inject, resource, Injectable } from '@angular/core';
|
|
3
|
+
import { OlGeometryService } from '@angular-helpers/openlayers/core';
|
|
4
|
+
import { Style, Icon, Stroke, RegularShape, Fill } from 'ol/style';
|
|
5
|
+
import { LineString, Point } from 'ol/geom';
|
|
3
6
|
|
|
4
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Service exposing geometry helpers and MIL-STD-2525 symbology rendering.
|
|
9
|
+
*
|
|
10
|
+
* - `createEllipse`, `createSector`, `createDonut` are **pure math** and
|
|
11
|
+
* delegate to {@link OlGeometryService} in core.
|
|
12
|
+
* - `createMilSymbol` uses the milsymbol library via Angular resource loading.
|
|
13
|
+
*/
|
|
5
14
|
class OlMilitaryService {
|
|
15
|
+
idCounter = 0;
|
|
16
|
+
geometryService = inject(OlGeometryService);
|
|
17
|
+
/**
|
|
18
|
+
* Resource managing the lazy-loading of the milsymbol library.
|
|
19
|
+
* Angular resource provides native signals for value, loading state, and errors.
|
|
20
|
+
*/
|
|
21
|
+
msResource = resource({ ...(ngDevMode ? { debugName: "msResource" } : /* istanbul ignore next */ {}), loader: () => import('milsymbol') });
|
|
22
|
+
/** Signal indicating if the milsymbol library is currently being loaded. */
|
|
23
|
+
isLoading = this.msResource.isLoading;
|
|
24
|
+
constructor() { }
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Geometry helpers (delegated to core)
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
/**
|
|
29
|
+
* Build a `Feature<Polygon>` approximating an ellipse centered at
|
|
30
|
+
* `config.center`. See {@link EllipseConfig} for parameter semantics.
|
|
31
|
+
*/
|
|
6
32
|
createEllipse(config) {
|
|
7
|
-
return
|
|
33
|
+
return this.geometryService.createEllipse(config);
|
|
8
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Build a `Feature<Polygon>` for a circular sector (pie slice).
|
|
37
|
+
* See {@link SectorConfig} for parameter semantics.
|
|
38
|
+
*/
|
|
9
39
|
createSector(config) {
|
|
10
|
-
return
|
|
40
|
+
return this.geometryService.createSector(config);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Build a `Feature<Polygon>` for a donut (annular ring).
|
|
44
|
+
*/
|
|
45
|
+
createDonut(config) {
|
|
46
|
+
return this.geometryService.createDonut(config);
|
|
47
|
+
}
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// MIL-STD-2525 symbology (lazy `milsymbol` load)
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
/**
|
|
52
|
+
* Pre-load the optional `milsymbol` peer dependency.
|
|
53
|
+
* Since resource() starts loading immediately, this simply returns a promise
|
|
54
|
+
* that resolves when the resource is ready.
|
|
55
|
+
*/
|
|
56
|
+
async preloadMilsymbol() {
|
|
57
|
+
this.assertBrowser();
|
|
58
|
+
// We can just await the dynamic import again; the browser/bundler will
|
|
59
|
+
// return the same module instantly if already loaded by the resource.
|
|
60
|
+
await import('milsymbol');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build a MIL-STD-2525 symbol feature asynchronously.
|
|
64
|
+
* Waits for the milsymbol resource to resolve.
|
|
65
|
+
*/
|
|
66
|
+
async createMilSymbol(config) {
|
|
67
|
+
this.assertBrowser();
|
|
68
|
+
this.assertSidc(config.sidc);
|
|
69
|
+
// Dynamic import ensures we have the module reference even if called
|
|
70
|
+
// before the resource signal has propagated.
|
|
71
|
+
const msModule = await import('milsymbol');
|
|
72
|
+
return this.buildSymbolFeature(config, msModule);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Build a MIL-STD-2525 symbol feature synchronously.
|
|
76
|
+
* Throws if `milsymbol` resource is not ready.
|
|
77
|
+
*/
|
|
78
|
+
createMilSymbolSync(config) {
|
|
79
|
+
this.assertBrowser();
|
|
80
|
+
this.assertSidc(config.sidc);
|
|
81
|
+
const msModule = this.msResource.value();
|
|
82
|
+
if (!msModule) {
|
|
83
|
+
throw new Error('milsymbol is not loaded yet. Call preloadMilsymbol() or use the async createMilSymbol().');
|
|
84
|
+
}
|
|
85
|
+
return this.buildSymbolFeature(config, msModule);
|
|
86
|
+
}
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// Internals
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
nextId(kind) {
|
|
91
|
+
return `${kind}-${++this.idCounter}`;
|
|
92
|
+
}
|
|
93
|
+
buildSymbolFeature(config, msModule) {
|
|
94
|
+
const { sidc, position, properties, quantity, ...rest } = config;
|
|
95
|
+
const milOptions = {
|
|
96
|
+
...rest,
|
|
97
|
+
...(quantity !== undefined ? { quantity: String(quantity) } : {}),
|
|
98
|
+
};
|
|
99
|
+
const ms = msModule;
|
|
100
|
+
const SymbolClass = ms.default?.Symbol || ms.Symbol;
|
|
101
|
+
const symbol = new SymbolClass(sidc, milOptions);
|
|
102
|
+
const style = this.symbolToStyleResult(symbol);
|
|
103
|
+
const mergedProperties = { sidc, ...milOptions, ...properties };
|
|
104
|
+
return {
|
|
105
|
+
id: this.nextId('symbol'),
|
|
106
|
+
geometry: { type: 'Point', coordinates: position },
|
|
107
|
+
properties: mergedProperties,
|
|
108
|
+
style: { icon: { src: style.src, size: style.size, anchor: style.anchor } },
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
symbolToStyleResult(symbol) {
|
|
112
|
+
const svg = symbol.asSVG();
|
|
113
|
+
const { width, height } = symbol.getSize();
|
|
114
|
+
const { x: ax, y: ay } = symbol.getAnchor();
|
|
115
|
+
return {
|
|
116
|
+
src: `data:image/svg+xml;base64,${this.encodeBase64Utf8(svg)}`,
|
|
117
|
+
size: [width, height],
|
|
118
|
+
anchor: [ax / width, ay / height],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
encodeBase64Utf8(input) {
|
|
122
|
+
return btoa(unescape(encodeURIComponent(input)));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Generates a canvas and anchor for a MIL-STD-2525 symbol.
|
|
126
|
+
* Requires milsymbol to be loaded (synchronous).
|
|
127
|
+
*/
|
|
128
|
+
createUnitStyle(sidc, selected = false, size = 30) {
|
|
129
|
+
const msModule = this.msResource.value();
|
|
130
|
+
if (!msModule)
|
|
131
|
+
return null;
|
|
132
|
+
const ms = msModule;
|
|
133
|
+
const SymbolClass = ms.default?.Symbol || ms.Symbol;
|
|
134
|
+
const symbol = new SymbolClass(sidc, {
|
|
135
|
+
size,
|
|
136
|
+
strokeWidth: selected ? 6 : 4,
|
|
137
|
+
});
|
|
138
|
+
const canvas = symbol.asCanvas();
|
|
139
|
+
const anchor = symbol.getAnchor();
|
|
140
|
+
return {
|
|
141
|
+
image: {
|
|
142
|
+
img: canvas,
|
|
143
|
+
size: [canvas.width, canvas.height],
|
|
144
|
+
anchor: [anchor.x / canvas.width, anchor.y / canvas.height],
|
|
145
|
+
},
|
|
146
|
+
zIndex: selected ? 100 : 10,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
assertSidc(sidc) {
|
|
150
|
+
if (typeof sidc !== 'string' || sidc.length < 10) {
|
|
151
|
+
throw new TypeError('sidc must be a non-empty MIL-STD-2525 SIDC string');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
assertBrowser() {
|
|
155
|
+
if (typeof window === 'undefined') {
|
|
156
|
+
throw new Error('createMilSymbol requires a browser environment');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlMilitaryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
160
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlMilitaryService });
|
|
161
|
+
}
|
|
162
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlMilitaryService, decorators: [{
|
|
163
|
+
type: Injectable
|
|
164
|
+
}], ctorParameters: () => [] });
|
|
165
|
+
|
|
166
|
+
// Tactical Graphics Service — investigation and prototype for military line drawing
|
|
167
|
+
/**
|
|
168
|
+
* Service providing styles and geometry generators for military tactical graphics
|
|
169
|
+
* such as battle fronts, axes of attack, and boundaries.
|
|
170
|
+
*
|
|
171
|
+
* NOTE: For point symbols (units), it delegates to {@link OlMilitaryService}
|
|
172
|
+
* for lazy-loading `milsymbol`.
|
|
173
|
+
*/
|
|
174
|
+
class OlTacticalGraphicsService {
|
|
175
|
+
idCounter = 0;
|
|
176
|
+
militaryService = inject(OlMilitaryService);
|
|
177
|
+
/**
|
|
178
|
+
* Creates a LineString feature representing a battle front.
|
|
179
|
+
*/
|
|
180
|
+
createFrontLine(coordinates, direction = 'friendly') {
|
|
181
|
+
return {
|
|
182
|
+
id: this.nextId('front-line'),
|
|
183
|
+
geometry: { type: 'LineString', coordinates },
|
|
184
|
+
properties: { tacticalType: 'front-line', direction },
|
|
185
|
+
};
|
|
11
186
|
}
|
|
12
|
-
|
|
187
|
+
/**
|
|
188
|
+
* Creates a LineString feature representing an attack arrow.
|
|
189
|
+
*/
|
|
190
|
+
createAttackArrow(coordinates, direction = 'friendly') {
|
|
13
191
|
return {
|
|
14
|
-
id:
|
|
15
|
-
geometry: { type: '
|
|
192
|
+
id: this.nextId('attack-arrow'),
|
|
193
|
+
geometry: { type: 'LineString', coordinates },
|
|
194
|
+
properties: { tacticalType: 'attack-arrow', direction },
|
|
16
195
|
};
|
|
17
196
|
}
|
|
18
|
-
|
|
19
|
-
|
|
197
|
+
/**
|
|
198
|
+
* Creates a Polygon feature representing a control zone.
|
|
199
|
+
*/
|
|
200
|
+
createControlZone(coordinates, direction = 'friendly') {
|
|
201
|
+
return {
|
|
202
|
+
id: this.nextId('control-zone'),
|
|
203
|
+
geometry: { type: 'Polygon', coordinates },
|
|
204
|
+
properties: { tacticalType: 'control-zone', direction },
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Creates a Point feature representing a military unit.
|
|
209
|
+
* @param sidc - Symbol Identification Code (MIL-STD-2525 / APP-6)
|
|
210
|
+
*/
|
|
211
|
+
createUnit(coordinate, sidc, name) {
|
|
212
|
+
return {
|
|
213
|
+
id: this.nextId('unit'),
|
|
214
|
+
geometry: { type: 'Point', coordinates: coordinate },
|
|
215
|
+
properties: { tacticalType: 'unit', sidc, name },
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
nextId(kind) {
|
|
219
|
+
return `${kind}-${++this.idCounter}`;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Style for Troop Units using milsymbol.
|
|
223
|
+
* NOTE: Requires milsymbol to be pre-loaded via OlMilitaryService.
|
|
224
|
+
*/
|
|
225
|
+
createUnitStyle(sidc, selected = false) {
|
|
226
|
+
// We delegate the style calculation to militaryService which handles the lazy-load state.
|
|
227
|
+
const styleProperties = this.militaryService.createUnitStyle(sidc, selected);
|
|
228
|
+
if (!styleProperties)
|
|
229
|
+
return null;
|
|
230
|
+
return new Style({
|
|
231
|
+
image: new Icon({
|
|
232
|
+
img: styleProperties.image.img,
|
|
233
|
+
size: styleProperties.image.size,
|
|
234
|
+
anchor: styleProperties.image.anchor,
|
|
235
|
+
}),
|
|
236
|
+
zIndex: styleProperties.zIndex,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Style for Battle Fronts (Complex LineString with teeth).
|
|
241
|
+
*/
|
|
242
|
+
createFrontLineStyle(color, direction = 'friendly') {
|
|
243
|
+
return (feature, resolution) => {
|
|
244
|
+
const geometry = feature.getGeometry();
|
|
245
|
+
if (!(geometry instanceof LineString))
|
|
246
|
+
return [];
|
|
247
|
+
const styles = [
|
|
248
|
+
new Style({
|
|
249
|
+
stroke: new Stroke({
|
|
250
|
+
color,
|
|
251
|
+
width: 3,
|
|
252
|
+
lineDash: direction === 'hostile' ? [10, 10] : undefined,
|
|
253
|
+
}),
|
|
254
|
+
}),
|
|
255
|
+
];
|
|
256
|
+
const coords = geometry.getCoordinates();
|
|
257
|
+
const stride = 40 * resolution; // Spacing between markers
|
|
258
|
+
let distSoFar = 0;
|
|
259
|
+
for (let i = 0; i < coords.length - 1; i++) {
|
|
260
|
+
const p1 = coords[i];
|
|
261
|
+
const p2 = coords[i + 1];
|
|
262
|
+
const dx = p2[0] - p1[0];
|
|
263
|
+
const dy = p2[1] - p1[1];
|
|
264
|
+
const len = Math.sqrt(dx * dx + dy * dy);
|
|
265
|
+
const angle = Math.atan2(dy, dx);
|
|
266
|
+
while (distSoFar < len) {
|
|
267
|
+
const ratio = distSoFar / len;
|
|
268
|
+
const pos = [p1[0] + dx * ratio, p1[1] + dy * ratio];
|
|
269
|
+
// Add "teeth" or spikes along the line
|
|
270
|
+
styles.push(new Style({
|
|
271
|
+
geometry: new Point(pos),
|
|
272
|
+
image: new RegularShape({
|
|
273
|
+
fill: new Fill({ color }),
|
|
274
|
+
points: direction === 'friendly' ? 20 : 3, // Semicircle vs Triangle
|
|
275
|
+
radius: 6,
|
|
276
|
+
rotation: -angle + (direction === 'friendly' ? 0 : Math.PI / 2),
|
|
277
|
+
angle: direction === 'friendly' ? angle + Math.PI / 2 : 0,
|
|
278
|
+
}),
|
|
279
|
+
}));
|
|
280
|
+
distSoFar += stride;
|
|
281
|
+
}
|
|
282
|
+
distSoFar -= len;
|
|
283
|
+
}
|
|
284
|
+
return styles;
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Style for Troop Movements (Arrows).
|
|
289
|
+
*/
|
|
290
|
+
createAttackArrowStyle(color) {
|
|
291
|
+
return (feature) => {
|
|
292
|
+
const geometry = feature.getGeometry();
|
|
293
|
+
if (!(geometry instanceof LineString))
|
|
294
|
+
return [];
|
|
295
|
+
const coords = geometry.getCoordinates();
|
|
296
|
+
if (coords.length < 2)
|
|
297
|
+
return [];
|
|
298
|
+
const last = coords[coords.length - 1];
|
|
299
|
+
const prev = coords[coords.length - 2];
|
|
300
|
+
const angle = Math.atan2(last[1] - prev[1], last[0] - prev[0]);
|
|
301
|
+
return [
|
|
302
|
+
new Style({
|
|
303
|
+
stroke: new Stroke({ color, width: 4, lineDash: [8, 4] }),
|
|
304
|
+
}),
|
|
305
|
+
new Style({
|
|
306
|
+
geometry: new Point(last),
|
|
307
|
+
image: new RegularShape({
|
|
308
|
+
fill: new Fill({ color }),
|
|
309
|
+
points: 3,
|
|
310
|
+
radius: 14,
|
|
311
|
+
rotation: -angle + Math.PI / 2,
|
|
312
|
+
}),
|
|
313
|
+
}),
|
|
314
|
+
];
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Style for Control Zones (Polygons).
|
|
319
|
+
*/
|
|
320
|
+
createZoneStyle(color, opacity = 0.2) {
|
|
321
|
+
return new Style({
|
|
322
|
+
fill: new Fill({ color: this.hexToRgba(color, opacity) }),
|
|
323
|
+
stroke: new Stroke({ color, width: 2 }),
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
hexToRgba(hex, alpha) {
|
|
327
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
328
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
329
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
330
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
331
|
+
}
|
|
332
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlTacticalGraphicsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
333
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlTacticalGraphicsService });
|
|
20
334
|
}
|
|
21
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
335
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlTacticalGraphicsService, decorators: [{
|
|
22
336
|
type: Injectable
|
|
23
337
|
}] });
|
|
24
338
|
|
|
25
339
|
function withMilitary() {
|
|
26
|
-
return {
|
|
340
|
+
return {
|
|
341
|
+
kind: 'military',
|
|
342
|
+
providers: [OlMilitaryService, OlTacticalGraphicsService],
|
|
343
|
+
};
|
|
27
344
|
}
|
|
28
345
|
function provideMilitary() {
|
|
29
346
|
return withMilitary();
|
|
@@ -35,4 +352,4 @@ function provideMilitary() {
|
|
|
35
352
|
* Generated bundle index. Do not edit.
|
|
36
353
|
*/
|
|
37
354
|
|
|
38
|
-
export { OlMilitaryService, provideMilitary, withMilitary };
|
|
355
|
+
export { OlMilitaryService, OlTacticalGraphicsService, provideMilitary, withMilitary };
|
|
@@ -2,6 +2,7 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { inject, ElementRef, input, output, DestroyRef, effect, ChangeDetectionStrategy, Component, Directive, EnvironmentInjector, ApplicationRef, createComponent, Injectable } from '@angular/core';
|
|
3
3
|
import Overlay from 'ol/Overlay';
|
|
4
4
|
import { OlMapService, OlZoneHelper } from '@angular-helpers/openlayers/core';
|
|
5
|
+
import { OlLayerService } from '@angular-helpers/openlayers/layers';
|
|
5
6
|
|
|
6
7
|
// OlPopupComponent — declarative popup with content projection.
|
|
7
8
|
/**
|
|
@@ -106,8 +107,8 @@ class OlPopupComponent {
|
|
|
106
107
|
this.overlay = null;
|
|
107
108
|
this.currentMap = null;
|
|
108
109
|
}
|
|
109
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
110
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
110
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlPopupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
111
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.13", type: OlPopupComponent, isStandalone: true, selector: "ol-popup", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, positioning: { classPropertyName: "positioning", publicName: "positioning", isSignal: true, isRequired: false, transformFunction: null }, autoPan: { classPropertyName: "autoPan", publicName: "autoPan", isSignal: true, isRequired: false, transformFunction: null }, closeButton: { classPropertyName: "closeButton", publicName: "closeButton", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { attributes: { "role": "dialog" } }, ngImport: i0, template: `
|
|
111
112
|
@if (closeButton()) {
|
|
112
113
|
<button type="button" class="ol-popup-close" aria-label="Close" (click)="onCloseClick()">
|
|
113
114
|
×
|
|
@@ -116,7 +117,7 @@ class OlPopupComponent {
|
|
|
116
117
|
<ng-content />
|
|
117
118
|
`, isInline: true, styles: [":host{display:block;position:relative}.ol-popup-close{position:absolute;top:4px;right:4px;width:20px;height:20px;padding:0;border:none;background:transparent;font-size:16px;line-height:1;cursor:pointer;color:inherit}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
118
119
|
}
|
|
119
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
120
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlPopupComponent, decorators: [{
|
|
120
121
|
type: Component,
|
|
121
122
|
args: [{ selector: 'ol-popup', changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
122
123
|
@if (closeButton()) {
|
|
@@ -231,10 +232,10 @@ class OlTooltipDirective {
|
|
|
231
232
|
this.listener = null;
|
|
232
233
|
this.currentMap = null;
|
|
233
234
|
}
|
|
234
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
235
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.
|
|
235
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
236
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.13", type: OlTooltipDirective, isStandalone: true, selector: "[olTooltip]", inputs: { olTooltip: { classPropertyName: "olTooltip", publicName: "olTooltip", isSignal: true, isRequired: true, transformFunction: null }, olTooltipLayer: { classPropertyName: "olTooltipLayer", publicName: "olTooltipLayer", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
|
|
236
237
|
}
|
|
237
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
238
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlTooltipDirective, decorators: [{
|
|
238
239
|
type: Directive,
|
|
239
240
|
args: [{
|
|
240
241
|
selector: '[olTooltip]',
|
|
@@ -409,10 +410,10 @@ class OlPopupService {
|
|
|
409
410
|
this.popups.set(id, { id, overlay, componentRef: ref, dispose });
|
|
410
411
|
});
|
|
411
412
|
}
|
|
412
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
413
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.
|
|
413
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlPopupService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
414
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlPopupService });
|
|
414
415
|
}
|
|
415
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
416
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.13", ngImport: i0, type: OlPopupService, decorators: [{
|
|
416
417
|
type: Injectable
|
|
417
418
|
}], ctorParameters: () => [] });
|
|
418
419
|
// -----------------------------------------------------------------------------
|
|
@@ -446,7 +447,7 @@ function applyOverlayConfig(overlay, config) {
|
|
|
446
447
|
}
|
|
447
448
|
|
|
448
449
|
function withOverlays() {
|
|
449
|
-
return { kind: 'overlays', providers: [OlPopupService] };
|
|
450
|
+
return { kind: 'overlays', providers: [OlLayerService, OlPopupService] };
|
|
450
451
|
}
|
|
451
452
|
function provideOverlays() {
|
|
452
453
|
return withOverlays();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-helpers/openlayers",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.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": {
|
|
@@ -32,9 +32,13 @@
|
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@angular/common": "^21.0.0",
|
|
34
34
|
"@angular/core": "^21.0.0",
|
|
35
|
+
"milsymbol": "^3.0.0",
|
|
35
36
|
"ol": "^10.0.0"
|
|
36
37
|
},
|
|
37
38
|
"peerDependenciesMeta": {
|
|
39
|
+
"milsymbol": {
|
|
40
|
+
"optional": true
|
|
41
|
+
},
|
|
38
42
|
"ol": {
|
|
39
43
|
"optional": false
|
|
40
44
|
}
|
|
@@ -78,4 +82,4 @@
|
|
|
78
82
|
"dependencies": {
|
|
79
83
|
"tslib": "^2.3.0"
|
|
80
84
|
}
|
|
81
|
-
}
|
|
85
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { InjectionToken, OnInit, ElementRef } from '@angular/core';
|
|
3
3
|
import OLMap from 'ol/Map';
|
|
4
4
|
import { OlFeature } from '@angular-helpers/openlayers/core';
|
|
5
5
|
|
|
@@ -87,7 +87,7 @@ interface LayerSwitcherItem {
|
|
|
87
87
|
/** Display name for the layer */
|
|
88
88
|
name: string;
|
|
89
89
|
/** Type of the layer */
|
|
90
|
-
type: 'vector' | 'tile' | 'image';
|
|
90
|
+
type: 'vector' | 'tile' | 'image' | 'heatmap';
|
|
91
91
|
/** Whether the layer is currently visible */
|
|
92
92
|
visible: boolean;
|
|
93
93
|
/** Opacity of the layer (0-1) */
|
|
@@ -114,7 +114,7 @@ type LayerSwitcherPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-
|
|
|
114
114
|
* </ol-layer-switcher>
|
|
115
115
|
* ```
|
|
116
116
|
*/
|
|
117
|
-
declare class OlLayerSwitcherComponent {
|
|
117
|
+
declare class OlLayerSwitcherComponent implements OnInit {
|
|
118
118
|
position: _angular_core.InputSignal<"top-left" | "top-right" | "bottom-left" | "bottom-right">;
|
|
119
119
|
layers: _angular_core.InputSignal<LayerSwitcherItem[]>;
|
|
120
120
|
collapsible: _angular_core.InputSignal<boolean>;
|
|
@@ -129,6 +129,7 @@ declare class OlLayerSwitcherComponent {
|
|
|
129
129
|
opacity: number;
|
|
130
130
|
}>;
|
|
131
131
|
protected isCollapsed: _angular_core.WritableSignal<boolean>;
|
|
132
|
+
ngOnInit(): void;
|
|
132
133
|
toggleCollapsed(): void;
|
|
133
134
|
toggleLayer(id: string): void;
|
|
134
135
|
setOpacity(id: string, event: Event): void;
|
|
@@ -197,6 +198,25 @@ interface ControlConfig {
|
|
|
197
198
|
className?: string;
|
|
198
199
|
}
|
|
199
200
|
|
|
201
|
+
declare class OlGeolocationControlComponent {
|
|
202
|
+
private mapService;
|
|
203
|
+
private zoneHelper;
|
|
204
|
+
private destroyRef;
|
|
205
|
+
position: _angular_core.InputSignal<ControlPosition>;
|
|
206
|
+
trackingChange: _angular_core.OutputEmitterRef<boolean>;
|
|
207
|
+
controlElement: ElementRef<HTMLElement>;
|
|
208
|
+
protected tracking: _angular_core.WritableSignal<boolean>;
|
|
209
|
+
private control?;
|
|
210
|
+
private geolocation?;
|
|
211
|
+
private positionFeature?;
|
|
212
|
+
private accuracyFeature?;
|
|
213
|
+
private layer?;
|
|
214
|
+
constructor();
|
|
215
|
+
toggleTracking(): void;
|
|
216
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<OlGeolocationControlComponent, never>;
|
|
217
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<OlGeolocationControlComponent, "ol-geolocation-control", never, { "position": { "alias": "position"; "required": false; "isSignal": true; }; }, { "trackingChange": "trackingChange"; }, never, never, true, never>;
|
|
218
|
+
}
|
|
219
|
+
|
|
200
220
|
declare class OlControlService {
|
|
201
221
|
addCustomControl(element: HTMLElement, position: ControlPosition): void;
|
|
202
222
|
removeCustomControl(element: HTMLElement): void;
|
|
@@ -211,5 +231,5 @@ declare class OlControlService {
|
|
|
211
231
|
declare function withControls(): OlFeature<'controls'>;
|
|
212
232
|
declare function provideControls(): OlFeature<'controls'>;
|
|
213
233
|
|
|
214
|
-
export { OlAttributionControlComponent, OlBasemapSwitcherComponent, OlControlService, OlFullscreenControlComponent, OlLayerSwitcherComponent, OlRotateControlComponent, OlScaleLineControlComponent, OlZoomControlComponent, ROTATE_CONTROL_MAP_SERVICE, provideControls, withControls };
|
|
234
|
+
export { OlAttributionControlComponent, OlBasemapSwitcherComponent, OlControlService, OlFullscreenControlComponent, OlGeolocationControlComponent, OlLayerSwitcherComponent, OlRotateControlComponent, OlScaleLineControlComponent, OlZoomControlComponent, ROTATE_CONTROL_MAP_SERVICE, provideControls, withControls };
|
|
215
235
|
export type { BasemapConfig, BasemapSwitcherPosition, ControlConfig, ControlPosition, LayerSwitcherItem, LayerSwitcherPosition, RotateControlMapService };
|