@artsdatabanken/nbic-map-component 0.3.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 +170 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/geometry-analysis-ERCBMJB7.js +37 -0
- package/dist/index.cjs +3796 -0
- package/dist/index.d.cts +805 -0
- package/dist/index.d.ts +805 -0
- package/dist/index.js +3711 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# nbic-map-component
|
|
2
|
+
|
|
3
|
+
Shared, framework-agnostic map component built on OpenLayers, designed to be used by host applications (Angular, React, Lit, plain TS/JS) through a stable API.
|
|
4
|
+
|
|
5
|
+
The library separates what the host application wants to do (MapApi) from how it is rendered (MapEngine / OpenLayers), making it easier to maintain, test, and extend.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
```bash
|
|
11
|
+
The architecture is intentionally layered:
|
|
12
|
+
|
|
13
|
+
Host app (Angular/React/Lit/vanilla)
|
|
14
|
+
|
|
|
15
|
+
| calls methods + subscribes to events
|
|
16
|
+
v
|
|
17
|
+
MapApi (public facade)
|
|
18
|
+
|
|
|
19
|
+
| delegates 1:1 to an engine, keeps public types stable
|
|
20
|
+
v
|
|
21
|
+
MapEngine (interface)
|
|
22
|
+
|
|
|
23
|
+
| concrete implementation chosen at runtime (or build-time)
|
|
24
|
+
v
|
|
25
|
+
OlMapEngine (OpenLayers implementation)
|
|
26
|
+
|
|
|
27
|
+
+--> LayerRegistry (indexes layers/sources)
|
|
28
|
+
+--> Adapters (LayerDef -> OL layer, StyleDef -> OL style, SourceDef -> OL source)
|
|
29
|
+
+--> Controllers (Draw / Hover / Select / Geo / Controls / Zoom)
|
|
30
|
+
|
|
|
31
|
+
v
|
|
32
|
+
OpenLayers (ol/Map, ol/layer, ol/source, ol/interaction, ol/style)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Design description
|
|
36
|
+
```bash
|
|
37
|
+
The host application (Angular, React, Lit, etc.):
|
|
38
|
+
• Owns application state
|
|
39
|
+
• Decides when and what to draw (layers, features, interactions)
|
|
40
|
+
• Talks only to MapApi
|
|
41
|
+
|
|
42
|
+
It never accesses OpenLayers directly.
|
|
43
|
+
|
|
44
|
+
MapApi
|
|
45
|
+
• Public API exposed by nbic-map-component
|
|
46
|
+
• Stable contract for host applications
|
|
47
|
+
• Methods like:
|
|
48
|
+
• adding/removing layers
|
|
49
|
+
• starting/stopping drawing
|
|
50
|
+
• selecting features
|
|
51
|
+
• controlling interactions
|
|
52
|
+
|
|
53
|
+
MapEngine
|
|
54
|
+
• Internal orchestration layer
|
|
55
|
+
• Translates MapApi calls into engine actions
|
|
56
|
+
• No OpenLayers imports
|
|
57
|
+
• Makes it possible to swap rendering engines in the future
|
|
58
|
+
|
|
59
|
+
OlMapEngine
|
|
60
|
+
• Concrete implementation using OpenLayers
|
|
61
|
+
• Owns:
|
|
62
|
+
• ol/Map
|
|
63
|
+
• layers, sources, interactions
|
|
64
|
+
• OpenLayers-specific logic (cluster, hover, select, draw)
|
|
65
|
+
|
|
66
|
+
Why this design?
|
|
67
|
+
• Clear separation of concerns
|
|
68
|
+
• Host apps stay simple and future-proof
|
|
69
|
+
• OpenLayers complexity is fully encapsulated
|
|
70
|
+
• Easier testing and playground setup
|
|
71
|
+
````
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Internal structure
|
|
75
|
+
```bash
|
|
76
|
+
src/
|
|
77
|
+
├─ api/ # Public types & events (no OpenLayers imports)
|
|
78
|
+
│ ├─ types.ts
|
|
79
|
+
│ ├─ events.ts
|
|
80
|
+
│
|
|
81
|
+
├─ core/
|
|
82
|
+
│ ├─ MapApi.ts # Public facade
|
|
83
|
+
│ ├─ MapEngine.ts # Internal engine interface
|
|
84
|
+
│
|
|
85
|
+
│ └─ ol/
|
|
86
|
+
│ ├─ OlMapEngine.ts
|
|
87
|
+
│ ├─ adapters/ # Layer / source / style adapters
|
|
88
|
+
│ ├─ interactions/ # Draw, Hover, Select controllers
|
|
89
|
+
│ ├─ layers/ # LayerRegistry, base-layer logic
|
|
90
|
+
│ ├─ utils/ # Geometry, extent, projection helpers
|
|
91
|
+
│
|
|
92
|
+
├─ presets/ # Predefined layers & sources (WMTS, base maps)
|
|
93
|
+
│
|
|
94
|
+
└─ index.ts # Public entry point
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 🚀 Getting started
|
|
100
|
+
|
|
101
|
+
### Install dependencies
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm install
|
|
105
|
+
```
|
|
106
|
+
### Build the library
|
|
107
|
+
```bash
|
|
108
|
+
npm run build
|
|
109
|
+
```
|
|
110
|
+
### Run tests
|
|
111
|
+
```bash
|
|
112
|
+
npm run test
|
|
113
|
+
npm run test:watch
|
|
114
|
+
```
|
|
115
|
+
### Lint and format
|
|
116
|
+
```bash
|
|
117
|
+
npm run lint
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## 🧪 Playground (local testing)
|
|
121
|
+
This repo includes a small Vite-powered playground to test the component in the browser.
|
|
122
|
+
|
|
123
|
+
### Start it
|
|
124
|
+
```bash
|
|
125
|
+
npm run dev
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 📖 Usage
|
|
129
|
+
### Install via npm (once published):
|
|
130
|
+
```bash
|
|
131
|
+
npm install nbic-map-component
|
|
132
|
+
```
|
|
133
|
+
### Basic usage in Angular
|
|
134
|
+
```bash
|
|
135
|
+
import { NbicMapComponent, MapEvents } from 'nbic-map-component';
|
|
136
|
+
import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from '@angular/core';
|
|
137
|
+
|
|
138
|
+
export class AppComponent implements AfterViewInit {
|
|
139
|
+
@ViewChild('mapEl', { static: true }) mapEl!: ElementRef<HTMLDivElement>;
|
|
140
|
+
private map!: InstanceType<typeof NbicMapComponent>;
|
|
141
|
+
|
|
142
|
+
ngAfterViewInit(): void {
|
|
143
|
+
this.map = new NbicMapComponent({
|
|
144
|
+
target: this.mapEl.nativeElement,
|
|
145
|
+
projection: 'EPSG:3857', // View must match WMTS projection
|
|
146
|
+
center: [1157722.7042500454, 9208962.278247332],
|
|
147
|
+
zoom: 4,
|
|
148
|
+
minZoom: 1,
|
|
149
|
+
maxZoom: 18,
|
|
150
|
+
controls: { scaleLine: true, fullscreen: true, geolocation: true, zoom: true, attribution: true },
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
this.map.on(MapEvents.Ready, () => {
|
|
154
|
+
this.mapReadyAction.next(true);
|
|
155
|
+
this.map.activateHoverInfo();
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
### html
|
|
161
|
+
```bash
|
|
162
|
+
<div #mapEl class="map"></div>
|
|
163
|
+
```
|
|
164
|
+
### css
|
|
165
|
+
```bash
|
|
166
|
+
.map {
|
|
167
|
+
height: 60vh;
|
|
168
|
+
width: 100%;
|
|
169
|
+
}
|
|
170
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import "./chunk-MLKGABMK.js";
|
|
2
|
+
|
|
3
|
+
// src/core/ol/utils/geometry-analysis.ts
|
|
4
|
+
import Feature from "ol/Feature";
|
|
5
|
+
import OLGeoJSON from "ol/format/GeoJSON";
|
|
6
|
+
import kinks from "@turf/kinks";
|
|
7
|
+
var fmt = new OLGeoJSON();
|
|
8
|
+
function toGeoJSONFeature(map, input) {
|
|
9
|
+
const viewProj = String(map.getView().getProjection().getCode());
|
|
10
|
+
const feature = input instanceof Feature ? input : new Feature({ geometry: input });
|
|
11
|
+
return fmt.writeFeatureObject(feature, {
|
|
12
|
+
dataProjection: "EPSG:4326",
|
|
13
|
+
featureProjection: viewProj
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function checkSelfIntersections(map, input) {
|
|
17
|
+
const gj = toGeoJSONFeature(map, input);
|
|
18
|
+
const type = gj.geometry?.type;
|
|
19
|
+
if (!type || !["LineString", "Polygon", "MultiLineString", "MultiPolygon"].includes(type)) {
|
|
20
|
+
return { valid: true };
|
|
21
|
+
}
|
|
22
|
+
const out = kinks(gj);
|
|
23
|
+
const count = out?.features?.length ?? 0;
|
|
24
|
+
return count > 0 ? { valid: false, intersections: out } : { valid: true };
|
|
25
|
+
}
|
|
26
|
+
function intersectionPointsToOlFeatures(map, points) {
|
|
27
|
+
const viewProj = String(map.getView().getProjection().getCode());
|
|
28
|
+
return fmt.readFeatures(points, {
|
|
29
|
+
dataProjection: "EPSG:4326",
|
|
30
|
+
featureProjection: viewProj
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
checkSelfIntersections,
|
|
35
|
+
intersectionPointsToOlFeatures,
|
|
36
|
+
toGeoJSONFeature
|
|
37
|
+
};
|