@angular-helpers/openlayers 0.4.0 → 0.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.
- package/README.md +131 -38
- package/core/README.md +43 -0
- package/fesm2022/angular-helpers-openlayers-controls.mjs +289 -36
- package/fesm2022/angular-helpers-openlayers-core.mjs +410 -16
- package/fesm2022/angular-helpers-openlayers-interactions.mjs +529 -71
- package/fesm2022/angular-helpers-openlayers-layers.mjs +947 -311
- package/fesm2022/angular-helpers-openlayers-military.mjs +244 -144
- package/fesm2022/angular-helpers-openlayers-overlays.mjs +35 -11
- package/package.json +2 -2
- package/types/angular-helpers-openlayers-controls.d.ts +24 -4
- package/types/angular-helpers-openlayers-core.d.ts +197 -6
- package/types/angular-helpers-openlayers-interactions.d.ts +125 -31
- package/types/angular-helpers-openlayers-layers.d.ts +166 -21
- package/types/angular-helpers-openlayers-military.d.ts +84 -94
package/README.md
CHANGED
|
@@ -10,12 +10,14 @@ A modern Angular wrapper for OpenLayers with modular architecture, standalone co
|
|
|
10
10
|
- **Dual API** - Template for UI, Inputs for data, Services for operations
|
|
11
11
|
- **Tree-shaking** - Unused OpenLayers code is eliminated from your bundle
|
|
12
12
|
- **TypeScript First** - Full type safety with strict mode support
|
|
13
|
-
- **Military Features** -
|
|
13
|
+
- **Military Features** - True geodesic precision for ellipses and sectors, NATO symbology, and MGRS coordinates
|
|
14
|
+
- **Proj4 Integration** - Declarative registration of local coordinate systems (like UTM)
|
|
15
|
+
- **WebGL Accelerated** - Mapbox Vector Tiles (MVT) and GPU raster expressions
|
|
14
16
|
|
|
15
17
|
## Installation
|
|
16
18
|
|
|
17
19
|
```bash
|
|
18
|
-
|
|
20
|
+
pnpm add @angular-helpers/openlayers ol
|
|
19
21
|
```
|
|
20
22
|
|
|
21
23
|
## Quick Start
|
|
@@ -30,7 +32,14 @@ import { withLayers } from '@angular-helpers/openlayers/layers';
|
|
|
30
32
|
import { withControls } from '@angular-helpers/openlayers/controls';
|
|
31
33
|
|
|
32
34
|
export const appConfig: ApplicationConfig = {
|
|
33
|
-
providers: [
|
|
35
|
+
providers: [
|
|
36
|
+
provideOpenLayers(
|
|
37
|
+
withLayers(),
|
|
38
|
+
withControls(),
|
|
39
|
+
// Optional: Register custom coordinate systems with proj4
|
|
40
|
+
// withProjections(proj4, [{ code: 'EPSG:32630', proj4def: '...', extent: [...] }])
|
|
41
|
+
),
|
|
42
|
+
],
|
|
34
43
|
};
|
|
35
44
|
```
|
|
36
45
|
|
|
@@ -49,7 +58,6 @@ import { OlMapService } from '@angular-helpers/openlayers/core';
|
|
|
49
58
|
|
|
50
59
|
@Component({
|
|
51
60
|
selector: 'app-map',
|
|
52
|
-
standalone: true,
|
|
53
61
|
imports: [
|
|
54
62
|
OlMapComponent,
|
|
55
63
|
OlTileLayerComponent,
|
|
@@ -176,87 +184,150 @@ const handle = popups.openComponent({
|
|
|
176
184
|
|
|
177
185
|
`open` is idempotent by `id` and updates the existing overlay in place. `openComponent` always recreates the `ComponentRef` on a repeated id and disposes the previous one (`appRef.detachView` + `ref.destroy`) to avoid CD leaks. Calls made before the map is ready are queued and replayed on `OlMapService.onReady`.
|
|
178
186
|
|
|
179
|
-
##
|
|
187
|
+
## WebGL Layers — GPU-accelerated rendering
|
|
180
188
|
|
|
181
|
-
Available since `0.
|
|
189
|
+
Available since `0.3.0` from `@angular-helpers/openlayers/layers`.
|
|
190
|
+
|
|
191
|
+
WebGL layers render directly on the GPU, making them perfect for extremely heavy tile configurations (with real-time styling expressions) and massive coordinate datasets (10,000+ vector points).
|
|
192
|
+
|
|
193
|
+
### `<ol-webgl-tile-layer>` — Raster style manipulation
|
|
194
|
+
|
|
195
|
+
Renders tile layers (OSM, XYZ, MVT) via WebGL. Supports the dynamic application of WebGL tile styles (raster expressions) for dynamic, GPU-powered adjustments like brightness, contrast, saturation, and gamma.
|
|
196
|
+
|
|
197
|
+
```html
|
|
198
|
+
<ol-webgl-tile-layer
|
|
199
|
+
id="satellite-webgl"
|
|
200
|
+
source="xyz"
|
|
201
|
+
[url]="'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'"
|
|
202
|
+
[tileStyle]="{
|
|
203
|
+
brightness: 0.1,
|
|
204
|
+
contrast: 0.2,
|
|
205
|
+
saturation: -0.5
|
|
206
|
+
}"
|
|
207
|
+
/>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### `<ol-webgl-vector-layer>` — Smooth massive datasets (10k+ features)
|
|
211
|
+
|
|
212
|
+
Renders points, lines, and polygons using WebGL 2. For peak performance, hit detection is disabled by default, and styling must be declared using `FlatStyleLike` expressions rather than standard `ol/style/Style` instances.
|
|
213
|
+
|
|
214
|
+
```html
|
|
215
|
+
<ol-webgl-vector-layer
|
|
216
|
+
id="massive-points"
|
|
217
|
+
[features]="densePoints()"
|
|
218
|
+
[flatStyle]="{
|
|
219
|
+
'circle-radius': 6,
|
|
220
|
+
'circle-fill-color': '#10b981',
|
|
221
|
+
'stroke-color': '#334155',
|
|
222
|
+
'stroke-width': 1
|
|
223
|
+
}"
|
|
224
|
+
[disableHitDetection]="true"
|
|
225
|
+
/>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Rigorous cleanup guarantees that WebGL contexts, framebuffers, and active buffers are fully released on destroy (`layer.dispose()`), preventing GPU leaks.
|
|
182
229
|
|
|
183
|
-
|
|
230
|
+
## Geodesic Geometry Helpers
|
|
231
|
+
|
|
232
|
+
Available from `@angular-helpers/openlayers/core` via `OlGeometryService`.
|
|
233
|
+
|
|
234
|
+
Approximates standard shapes in metric space using true geodesic calculations (`Vincenty`'s formulae via `ol/sphere`). This means your shapes remain mathematically accurate and visually consistent (without map projection scale distortion) across massive global distances.
|
|
184
235
|
|
|
185
236
|
```typescript
|
|
186
|
-
import { inject, signal } from '@angular/core';
|
|
187
|
-
import {
|
|
237
|
+
import { inject, Component, signal } from '@angular/core';
|
|
238
|
+
import { OlGeometryService } from '@angular-helpers/openlayers/core';
|
|
188
239
|
import type { Feature } from '@angular-helpers/openlayers/core';
|
|
189
240
|
|
|
190
241
|
@Component({
|
|
191
|
-
// …
|
|
192
242
|
imports: [OlMapComponent, OlVectorLayerComponent],
|
|
193
243
|
template: `
|
|
194
244
|
<ol-map [center]="[2.17, 41.38]" [zoom]="8">
|
|
195
245
|
<ol-tile-layer id="osm" source="osm" />
|
|
196
|
-
<ol-vector-layer id="
|
|
246
|
+
<ol-vector-layer id="shapes" [features]="features()" />
|
|
197
247
|
</ol-map>
|
|
198
248
|
`,
|
|
199
249
|
})
|
|
200
|
-
export class
|
|
201
|
-
private
|
|
250
|
+
export class GeodesicDemo {
|
|
251
|
+
private geomSvc = inject(OlGeometryService);
|
|
202
252
|
features = signal<Feature[]>([]);
|
|
203
253
|
|
|
204
|
-
|
|
205
|
-
const ellipse = this.
|
|
254
|
+
ngOnInit() {
|
|
255
|
+
const ellipse = this.geomSvc.createEllipse({
|
|
206
256
|
center: [2.17, 41.38],
|
|
207
257
|
semiMajor: 6_000,
|
|
208
258
|
semiMinor: 3_000,
|
|
209
259
|
rotation: Math.PI / 6,
|
|
210
260
|
});
|
|
211
|
-
const sector = this.
|
|
261
|
+
const sector = this.geomSvc.createSector({
|
|
212
262
|
center: [-0.38, 39.47],
|
|
213
263
|
radius: 8_000,
|
|
214
264
|
startAngle: Math.PI / 6,
|
|
215
265
|
endAngle: Math.PI / 2,
|
|
216
266
|
});
|
|
217
|
-
const donut = this.
|
|
267
|
+
const donut = this.geomSvc.createDonut({
|
|
218
268
|
center: [-5.99, 37.39],
|
|
219
269
|
innerRadius: 5_000,
|
|
220
270
|
outerRadius: 10_000,
|
|
221
271
|
});
|
|
222
|
-
|
|
223
|
-
sidc: 'SFGPUCI-----',
|
|
224
|
-
position: [-3.7, 40.42],
|
|
225
|
-
size: 36,
|
|
226
|
-
});
|
|
227
|
-
this.features.set([ellipse, sector, donut, symbol]);
|
|
272
|
+
this.features.set([ellipse, sector, donut]);
|
|
228
273
|
}
|
|
229
274
|
}
|
|
230
275
|
```
|
|
231
276
|
|
|
232
|
-
### Geometry helpers
|
|
233
|
-
|
|
234
277
|
| Method | Output | Notes |
|
|
235
278
|
| ----------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------- |
|
|
236
279
|
| `createEllipse(config)` | `Feature<Polygon>` | Optional `rotation` in radians, configurable `segments` (default 64) |
|
|
237
280
|
| `createSector(config)` | `Feature<Polygon>` | Pie-slice (apex-arc-apex). `startAngle < endAngle ≤ start + 2π` |
|
|
238
281
|
| `createDonut(config)` | `Feature<Polygon>` | Two rings: outer CCW, inner CW (right-hand rule). Renders as an annular band with the basemap visible through the hole |
|
|
239
282
|
|
|
240
|
-
|
|
283
|
+
---
|
|
241
284
|
|
|
242
|
-
|
|
285
|
+
## Military Symbology & Tactical Graphics
|
|
243
286
|
|
|
244
|
-
|
|
287
|
+
Available since `0.4.0` from `@angular-helpers/openlayers/military`.
|
|
245
288
|
|
|
246
|
-
|
|
247
|
-
|
|
289
|
+
Exposes NATO MIL-STD-2525 symbol rendering backed by the optional [`milsymbol`](https://github.com/spatialillusions/milsymbol) peer dependency, plus tactical military graphic components (frontlines, attack vectors).
|
|
290
|
+
|
|
291
|
+
### MIL-STD-2525 Point Symbology (`OlMilitaryService`)
|
|
292
|
+
|
|
293
|
+
Lazy-loads the heavy `milsymbol` package dynamically on demand, returning a styled `Feature<Point>` so the vector layer renders it natively.
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
import { inject, Component, signal } from '@angular/core';
|
|
297
|
+
import { OlMilitaryService } from '@angular-helpers/openlayers/military';
|
|
298
|
+
import type { Feature } from '@angular-helpers/openlayers/core';
|
|
299
|
+
|
|
300
|
+
@Component({
|
|
301
|
+
imports: [OlMapComponent, OlVectorLayerComponent],
|
|
302
|
+
providers: [OlMilitaryService],
|
|
303
|
+
template: `
|
|
304
|
+
<ol-map [center]="[-3.7, 40.42]" [zoom]="8">
|
|
305
|
+
<ol-vector-layer id="military" [features]="features()" />
|
|
306
|
+
</ol-map>
|
|
307
|
+
`,
|
|
308
|
+
})
|
|
309
|
+
export class MilDemo {
|
|
310
|
+
private milSvc = inject(OlMilitaryService);
|
|
311
|
+
features = signal<Feature[]>([]);
|
|
312
|
+
|
|
313
|
+
async ngOnInit() {
|
|
314
|
+
const symbol = await this.milSvc.createMilSymbol({
|
|
315
|
+
sidc: 'SFGPUCI-----', // Friendly Infantry Unit
|
|
316
|
+
position: [-3.7, 40.42],
|
|
317
|
+
size: 36,
|
|
318
|
+
});
|
|
319
|
+
this.features.set([symbol]);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
248
322
|
```
|
|
249
323
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
size: 36,
|
|
255
|
-
uniqueDesignation: 'A1',
|
|
256
|
-
});
|
|
324
|
+
Install the optional peer dependency if utilizing NATO symbology:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
pnpm add milsymbol
|
|
257
328
|
```
|
|
258
329
|
|
|
259
|
-
Three
|
|
330
|
+
Three execution strategies:
|
|
260
331
|
|
|
261
332
|
- **`createMilSymbol(config)`** — async; lazy-loads on first call.
|
|
262
333
|
- **`createMilSymbolSync(config)`** — sync; throws if `milsymbol` is not loaded yet.
|
|
@@ -264,6 +335,28 @@ Three flavors:
|
|
|
264
335
|
|
|
265
336
|
The service throws clearly on non-browser environments (`createMilSymbol` requires `window`).
|
|
266
337
|
|
|
338
|
+
### Tactical Graphics (`OlTacticalGraphicsService`)
|
|
339
|
+
|
|
340
|
+
Builds advanced multi-point military tactical graphic features (frontlines with directional teeth, attack arrow coordinates) and provides custom styles.
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
import { OlTacticalGraphicsService } from '@angular-helpers/openlayers/military';
|
|
344
|
+
|
|
345
|
+
const tacticalSvc = inject(OlTacticalGraphicsService);
|
|
346
|
+
|
|
347
|
+
// Create a frontline graphic
|
|
348
|
+
const frontline = tacticalSvc.createFrontLine(
|
|
349
|
+
[
|
|
350
|
+
[2.1, 41.3],
|
|
351
|
+
[2.2, 41.4],
|
|
352
|
+
],
|
|
353
|
+
'friendly',
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
// Apply specialized style for frontline teeth
|
|
357
|
+
const frontlineStyle = tacticalSvc.createFrontLineStyle('#4f46e5', 'friendly');
|
|
358
|
+
```
|
|
359
|
+
|
|
267
360
|
## Architecture
|
|
268
361
|
|
|
269
362
|
### Data vs UI Separation
|
package/core/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# @angular-helpers/openlayers/core
|
|
2
|
+
|
|
3
|
+
Core library for Angular bindings to OpenLayers.
|
|
4
|
+
Provides essential models, services, and the base `<ol-map>` component.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
\`\`\`bash
|
|
9
|
+
npm install @angular-helpers/openlayers
|
|
10
|
+
\`\`\`
|
|
11
|
+
|
|
12
|
+
## Core Services & Components
|
|
13
|
+
|
|
14
|
+
- \`OlMapComponent\`: The root map component that manages the core OpenLayers `Map` instance.
|
|
15
|
+
- \`OlMapService\`: A service to retrieve and manage the map instance across child components.
|
|
16
|
+
- \`OlLayerService\`: Manages map layers dynamically.
|
|
17
|
+
- \`OlZoneHelper\`: Optimizes Angular change detection around OpenLayers events.
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
\`\`\`typescript
|
|
22
|
+
import { Component } from '@angular/core';
|
|
23
|
+
import { OlMapComponent } from '@angular-helpers/openlayers';
|
|
24
|
+
import { OlTileLayerComponent } from '@angular-helpers/openlayers/layers';
|
|
25
|
+
|
|
26
|
+
@Component({
|
|
27
|
+
selector: 'app-map-demo',
|
|
28
|
+
imports: [OlMapComponent, OlTileLayerComponent],
|
|
29
|
+
template: \`
|
|
30
|
+
<ol-map [center]="[0, 0]" [zoom]="4" class="map-container">
|
|
31
|
+
<ol-tile-layer source="osm"></ol-tile-layer>
|
|
32
|
+
</ol-map>
|
|
33
|
+
\`,
|
|
34
|
+
styles: [\`
|
|
35
|
+
.map-container {
|
|
36
|
+
width: 100%;
|
|
37
|
+
height: 400px;
|
|
38
|
+
display: block;
|
|
39
|
+
}
|
|
40
|
+
\`]
|
|
41
|
+
})
|
|
42
|
+
export class MapDemoComponent {}
|
|
43
|
+
\`\`\`
|