@geogirafe/lib-geoportal 1.1.0-dev.2536443365 → 1.1.0-dev.2557861681
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/api/apigeogirafeapp.d.ts +4 -0
- package/api/apigeogirafeapp.js +138 -12
- package/components/map/component.js +9 -8
- package/package.json +1 -1
- package/templates/api.html +52 -5
- package/templates/public/about.json +1 -1
- package/templates/public/api/data-cartoriviera.txt +8 -0
- package/templates/public/api/data-mapbs.txt +6 -0
- package/templates/public/api/marker-huge.png +0 -0
- package/templates/public/api/marker-plus.png +0 -0
- package/templates/public/api/marker2-plus.png +0 -0
- package/tools/main.d.ts +1 -1
- package/tools/main.js +1 -1
- package/tools/state/mapposition.d.ts +2 -0
- package/tools/state/mapposition.js +3 -1
- package/tools/url/permalinkmanager.d.ts +5 -0
- package/tools/url/permalinkmanager.js +55 -27
- package/tools/utils/utils.d.ts +5 -0
- package/tools/utils/utils.js +10 -0
package/api/apigeogirafeapp.d.ts
CHANGED
|
@@ -26,6 +26,10 @@ export default class GeoGirafeApi extends GirafeHTMLElement {
|
|
|
26
26
|
private manageCrosshairAttribute;
|
|
27
27
|
private manageTooltipAttribute;
|
|
28
28
|
private manageMarkersAttribute;
|
|
29
|
+
private markerStringToMapMarker;
|
|
30
|
+
private manageMarkersFileAttribute;
|
|
31
|
+
private readMarkersFromFile;
|
|
32
|
+
private lineToMarker;
|
|
29
33
|
private initialize;
|
|
30
34
|
private injectConfigMetaTags;
|
|
31
35
|
}
|
package/api/apigeogirafeapp.js
CHANGED
|
@@ -10,6 +10,22 @@ import MenuButtonComponent from '../components/menubutton/component.js';
|
|
|
10
10
|
import MapCustomContextMenuComponent from '../components/context-menu/custom-context-menu/component.js';
|
|
11
11
|
import SearchComponent from '../components/search/component.js';
|
|
12
12
|
import SelectionWindowComponent from '../components/selectionwindow/component.js';
|
|
13
|
+
import { splitTrimAndConvertToNumber } from '../tools/utils/utils.js';
|
|
14
|
+
const getImageSize = (url) => {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const img = new Image();
|
|
17
|
+
img.onload = () => {
|
|
18
|
+
resolve({
|
|
19
|
+
width: img.naturalWidth,
|
|
20
|
+
height: img.naturalHeight
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
img.onerror = () => {
|
|
24
|
+
reject(new Error(`Failed to load image: ${url}`));
|
|
25
|
+
};
|
|
26
|
+
img.src = url;
|
|
27
|
+
});
|
|
28
|
+
};
|
|
13
29
|
export default class GeoGirafeApi extends GirafeHTMLElement {
|
|
14
30
|
templateUrl = null;
|
|
15
31
|
styleUrls = null;
|
|
@@ -46,7 +62,7 @@ export default class GeoGirafeApi extends GirafeHTMLElement {
|
|
|
46
62
|
});
|
|
47
63
|
}
|
|
48
64
|
static get observedAttributes() {
|
|
49
|
-
return ['center', 'zoom', 'basemap', 'basemapselector', 'crosshair', 'tooltip', 'markers', 'layers'];
|
|
65
|
+
return ['center', 'zoom', 'basemap', 'basemapselector', 'crosshair', 'tooltip', 'markers', 'markersfile', 'layers'];
|
|
50
66
|
}
|
|
51
67
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
52
68
|
if (this.isInitialized) {
|
|
@@ -73,6 +89,9 @@ export default class GeoGirafeApi extends GirafeHTMLElement {
|
|
|
73
89
|
else if (name === 'markers') {
|
|
74
90
|
this.manageMarkersAttribute();
|
|
75
91
|
}
|
|
92
|
+
else if (name === 'markersfile') {
|
|
93
|
+
this.manageMarkersFileAttribute();
|
|
94
|
+
}
|
|
76
95
|
else if (name === 'layers') {
|
|
77
96
|
this.manageLayersAttribute();
|
|
78
97
|
}
|
|
@@ -95,6 +114,7 @@ export default class GeoGirafeApi extends GirafeHTMLElement {
|
|
|
95
114
|
this.manageCrosshairAttribute();
|
|
96
115
|
this.manageTooltipAttribute();
|
|
97
116
|
this.manageMarkersAttribute();
|
|
117
|
+
this.manageMarkersFileAttribute();
|
|
98
118
|
this.manageLayersAttribute();
|
|
99
119
|
this.manageSelectionboxAttribute();
|
|
100
120
|
this.manageUserInteraction();
|
|
@@ -245,17 +265,10 @@ export default class GeoGirafeApi extends GirafeHTMLElement {
|
|
|
245
265
|
const markers = this.getAttributeFromConfig('markers');
|
|
246
266
|
if (markers) {
|
|
247
267
|
const markerValues = markers.split(';');
|
|
248
|
-
for (const
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const y = Number(coords[1].trim());
|
|
253
|
-
if (!Number.isNaN(x) && !Number.isNaN(y)) {
|
|
254
|
-
const imageUrl = content[1].trim();
|
|
255
|
-
this.context.stateManager.state.position.markers.push({
|
|
256
|
-
position: [x, y],
|
|
257
|
-
imageUrl: imageUrl
|
|
258
|
-
});
|
|
268
|
+
for (const markerValue of markerValues) {
|
|
269
|
+
const marker = this.markerStringToMapMarker(markerValue);
|
|
270
|
+
if (marker) {
|
|
271
|
+
this.context.stateManager.state.position.markers.push(marker);
|
|
259
272
|
}
|
|
260
273
|
else {
|
|
261
274
|
console.warn('Invalid marker coordinates');
|
|
@@ -263,6 +276,119 @@ export default class GeoGirafeApi extends GirafeHTMLElement {
|
|
|
263
276
|
}
|
|
264
277
|
}
|
|
265
278
|
}
|
|
279
|
+
markerStringToMapMarker(markerValue) {
|
|
280
|
+
console.log('markerStringToMapMarker', markerValue);
|
|
281
|
+
const contentParts = markerValue.split('|');
|
|
282
|
+
const needToGuessThirdParameter = contentParts.length == 3;
|
|
283
|
+
if (needToGuessThirdParameter) {
|
|
284
|
+
console.warn(`Marker has only 3 Parameters! Guessing if third Parameter '${contentParts[2]}' is Size or Offset`);
|
|
285
|
+
}
|
|
286
|
+
const coords = contentParts[0].split(',');
|
|
287
|
+
const x = Number(coords[0].trim());
|
|
288
|
+
const y = Number(coords[1].trim());
|
|
289
|
+
if (!Number.isNaN(x) && !Number.isNaN(y)) {
|
|
290
|
+
const imageUrl = contentParts[1].trim();
|
|
291
|
+
let size;
|
|
292
|
+
let offset;
|
|
293
|
+
if (needToGuessThirdParameter) {
|
|
294
|
+
if (contentParts[2].match(/[+-]+/gm)) {
|
|
295
|
+
offset = splitTrimAndConvertToNumber(contentParts[2]);
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
size = splitTrimAndConvertToNumber(contentParts[2]);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
else if (contentParts.length > 2) {
|
|
302
|
+
size = splitTrimAndConvertToNumber(contentParts[2]);
|
|
303
|
+
offset = splitTrimAndConvertToNumber(contentParts[3]);
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
position: [x, y],
|
|
307
|
+
imageUrl: imageUrl,
|
|
308
|
+
size: size,
|
|
309
|
+
offset: offset
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
return undefined;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
manageMarkersFileAttribute() {
|
|
317
|
+
const markersFile = this.getAttributeFromConfig('markersfile');
|
|
318
|
+
if (markersFile) {
|
|
319
|
+
void this.readMarkersFromFile(markersFile).then((markers) => {
|
|
320
|
+
this.context.stateManager.state.position.markers.push(...markers);
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
async readMarkersFromFile(fileUrl) {
|
|
325
|
+
const response = await fetch(fileUrl);
|
|
326
|
+
if (!response.ok) {
|
|
327
|
+
console.warn(`Cannot read markers file '${fileUrl}': ${response.status} ${response.statusText}`);
|
|
328
|
+
return [];
|
|
329
|
+
}
|
|
330
|
+
const fileContent = await response.text();
|
|
331
|
+
const lines = fileContent
|
|
332
|
+
.split(/\r?\n/)
|
|
333
|
+
.map((line) => line.trim())
|
|
334
|
+
.filter((line) => line.length > 0);
|
|
335
|
+
if (lines.length < 2) {
|
|
336
|
+
return [];
|
|
337
|
+
}
|
|
338
|
+
const headers = lines[0].split('\t').map((header) => header.trim());
|
|
339
|
+
const pointIndex = headers.indexOf('point');
|
|
340
|
+
const iconIndex = headers.indexOf('icon');
|
|
341
|
+
const iconSizeIndex = headers.indexOf('iconSize');
|
|
342
|
+
const iconOffsetIndex = headers.indexOf('iconOffset');
|
|
343
|
+
if (pointIndex === -1 || iconIndex === -1) {
|
|
344
|
+
console.warn(`Invalid markers file '${fileUrl}': missing required 'point' or 'icon' column`);
|
|
345
|
+
return [];
|
|
346
|
+
}
|
|
347
|
+
const markers = [];
|
|
348
|
+
const legacy = fileUrl.includes('legacy');
|
|
349
|
+
for (const line of lines.slice(1)) {
|
|
350
|
+
await this.lineToMarker(line, pointIndex, iconIndex, iconSizeIndex, iconOffsetIndex, legacy).then((marker) => {
|
|
351
|
+
if (marker) {
|
|
352
|
+
markers.push(marker);
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
return markers;
|
|
357
|
+
}
|
|
358
|
+
async lineToMarker(line, pointIndex, iconIndex, iconSizeIndex, iconOffsetIndex, legacy) {
|
|
359
|
+
const columns = line.split('\t');
|
|
360
|
+
const coords = splitTrimAndConvertToNumber(columns[pointIndex]);
|
|
361
|
+
const imageUrl = columns[iconIndex]?.trim();
|
|
362
|
+
if (coords.length < 2 || !imageUrl || Number.isNaN(coords[0]) || Number.isNaN(coords[1])) {
|
|
363
|
+
console.warn(`Invalid marker line ': ${line}`);
|
|
364
|
+
return undefined;
|
|
365
|
+
}
|
|
366
|
+
// In the old WebGIS the coordinates are in the wrong order. This is to ensure compatibility with older data.
|
|
367
|
+
if (coords[0] < coords[1] && this.context.stateManager.state.projection === 'EPSG:2056') {
|
|
368
|
+
coords.reverse();
|
|
369
|
+
}
|
|
370
|
+
const size = iconSizeIndex >= 0 && columns[iconSizeIndex]?.trim()
|
|
371
|
+
? splitTrimAndConvertToNumber(columns[iconSizeIndex])
|
|
372
|
+
: undefined;
|
|
373
|
+
let offset = iconOffsetIndex >= 0 && columns[iconOffsetIndex]?.trim()
|
|
374
|
+
? splitTrimAndConvertToNumber(columns[iconOffsetIndex])
|
|
375
|
+
: undefined;
|
|
376
|
+
// In the old WebGIS the Offset referred to the Size of the original Image, while now it refers to the Size of the
|
|
377
|
+
// resized Image. This is to ensure compatibility with older data.
|
|
378
|
+
if (offset && size && legacy) {
|
|
379
|
+
await getImageSize(imageUrl).then((imageSize) => {
|
|
380
|
+
const scaleX = size[0] / imageSize.width;
|
|
381
|
+
const scaleY = size[1] / imageSize.height;
|
|
382
|
+
offset = [offset[0] * scaleX, offset[1] * scaleY];
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
return {
|
|
386
|
+
position: [coords[0], coords[1]],
|
|
387
|
+
imageUrl,
|
|
388
|
+
size,
|
|
389
|
+
offset
|
|
390
|
+
};
|
|
391
|
+
}
|
|
266
392
|
async initialize() {
|
|
267
393
|
await this.context.initialize();
|
|
268
394
|
// Register Coordinate Reference Systems (CRS) definitions in PROJ4
|
|
@@ -135,7 +135,7 @@ export default class MapComponent extends GirafeHTMLElement {
|
|
|
135
135
|
this.subscribe('position.markers', () => {
|
|
136
136
|
this.clearAllMarkers();
|
|
137
137
|
for (const marker of this.state.position.markers) {
|
|
138
|
-
this.addMarker(marker
|
|
138
|
+
this.addMarker(marker);
|
|
139
139
|
}
|
|
140
140
|
});
|
|
141
141
|
this.subscribe('globe.display', async () => {
|
|
@@ -177,7 +177,7 @@ export default class MapComponent extends GirafeHTMLElement {
|
|
|
177
177
|
}
|
|
178
178
|
this.showCrosshair(this.state.position);
|
|
179
179
|
for (const marker of this.state.position.markers) {
|
|
180
|
-
this.addMarker(marker
|
|
180
|
+
this.addMarker(marker);
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
});
|
|
@@ -1017,23 +1017,24 @@ export default class MapComponent extends GirafeHTMLElement {
|
|
|
1017
1017
|
this.state.position = position;
|
|
1018
1018
|
if (position.markers.length > 0) {
|
|
1019
1019
|
// Add marker to the map
|
|
1020
|
-
this.addMarker(position.markers[0]
|
|
1020
|
+
this.addMarker(position.markers[0]);
|
|
1021
1021
|
}
|
|
1022
1022
|
}
|
|
1023
1023
|
}
|
|
1024
1024
|
clearAllMarkers() {
|
|
1025
1025
|
this.markerSource.clear();
|
|
1026
1026
|
}
|
|
1027
|
-
addMarker(
|
|
1027
|
+
addMarker(mapMarker) {
|
|
1028
1028
|
const iconStyle = new Style({
|
|
1029
1029
|
image: new Icon({
|
|
1030
|
-
|
|
1031
|
-
src: imageUrl
|
|
1032
|
-
|
|
1030
|
+
displacement: mapMarker.offset,
|
|
1031
|
+
src: mapMarker.imageUrl,
|
|
1032
|
+
width: mapMarker.size ? mapMarker.size[0] : undefined,
|
|
1033
|
+
height: mapMarker.size ? mapMarker.size[1] : undefined
|
|
1033
1034
|
})
|
|
1034
1035
|
});
|
|
1035
1036
|
const marker = new Feature({
|
|
1036
|
-
geometry: new Point(position)
|
|
1037
|
+
geometry: new Point(mapMarker.position)
|
|
1037
1038
|
});
|
|
1038
1039
|
marker.setStyle(iconStyle);
|
|
1039
1040
|
this.markerSource.addFeature(marker);
|
package/package.json
CHANGED
package/templates/api.html
CHANGED
|
@@ -113,6 +113,10 @@
|
|
|
113
113
|
text-align: left;
|
|
114
114
|
margin-bottom: 1rem;
|
|
115
115
|
}
|
|
116
|
+
ul {
|
|
117
|
+
width: 100%;
|
|
118
|
+
margin: 0;
|
|
119
|
+
}
|
|
116
120
|
</style>
|
|
117
121
|
|
|
118
122
|
<script type="module" src="src/main.api.ts"></script>
|
|
@@ -290,6 +294,53 @@
|
|
|
290
294
|
</div>
|
|
291
295
|
</section>
|
|
292
296
|
|
|
297
|
+
<!-- Multiple markers with size and/or offset -->
|
|
298
|
+
<h2>Add multiple markers with size and/or offset on the map</h2>
|
|
299
|
+
<p class="descr">
|
|
300
|
+
Add multiple markers at the defined coordinates. <br />
|
|
301
|
+
You can specify size and offset.<br />
|
|
302
|
+
If you only specify three parameters, the third parameter can be the size if you <strong>don't</strong> include
|
|
303
|
+
a sign (e.g. <code>24,24</code>) or the offset if you <strong>do</strong> include a sign (e.g.
|
|
304
|
+
<code>+2,-6</code>).
|
|
305
|
+
</p>
|
|
306
|
+
<section>
|
|
307
|
+
<div class="row">
|
|
308
|
+
<div class="left">
|
|
309
|
+
<geogirafe-map markers="api.demo.markersWithSizeAndOrOffset" />
|
|
310
|
+
</div>
|
|
311
|
+
<div class="right"></div>
|
|
312
|
+
</div>
|
|
313
|
+
</section>
|
|
314
|
+
|
|
315
|
+
<!-- Multiple markers with size and/or offset -->
|
|
316
|
+
<h2>Add multiple markers on the map by providing a File/URL</h2>
|
|
317
|
+
<p class="descr">
|
|
318
|
+
You can provide a URL to a TXT file containing markers.<br />
|
|
319
|
+
Each line represents a marker with TAB-separated values.<br />
|
|
320
|
+
The file must contain the column names as header.
|
|
321
|
+
</p>
|
|
322
|
+
<p class="descr">Allowed column names:</p>
|
|
323
|
+
<ul>
|
|
324
|
+
<li><strong>point</strong>: coordinates where the amrker should be added.</li>
|
|
325
|
+
<li><strong>icon</strong>: url to the marker image</li>
|
|
326
|
+
<li><strong>iconSize</strong> (optional): size if the marker should be resized</li>
|
|
327
|
+
<li><strong>iconOffset</strong> (optional): offset if the marker should be shifted</li>
|
|
328
|
+
</ul>
|
|
329
|
+
<p class="descr">
|
|
330
|
+
Other columns will be ignored.<br />
|
|
331
|
+
Compatibility with the format used in the old GeoMapFish API will be managed if the URL to fo file contains the
|
|
332
|
+
keyword <code>legacy</code>.<br />
|
|
333
|
+
Coordinates can be given in both way (North,East) or (East,North) only if the SRID <code>CH:2056</code> is used.
|
|
334
|
+
</p>
|
|
335
|
+
<section>
|
|
336
|
+
<div class="row">
|
|
337
|
+
<div class="left">
|
|
338
|
+
<geogirafe-map markersfile="api.demo.markersFile" />
|
|
339
|
+
</div>
|
|
340
|
+
<div class="right"></div>
|
|
341
|
+
</div>
|
|
342
|
+
</section>
|
|
343
|
+
|
|
293
344
|
<!-- Layers -->
|
|
294
345
|
<h2>Add a layer to the map</h2>
|
|
295
346
|
<p class="descr">Add a layer to the map. The layer name must be defined in the themes.json file.</p>
|
|
@@ -302,7 +353,7 @@
|
|
|
302
353
|
</div>
|
|
303
354
|
</section>
|
|
304
355
|
|
|
305
|
-
<!--
|
|
356
|
+
<!-- Multiple layers -->
|
|
306
357
|
<h2>Add multiple layers to the map</h2>
|
|
307
358
|
<p class="descr">Add multiple layers to the map. The layer names must be defined in the themes.json file.</p>
|
|
308
359
|
<section>
|
|
@@ -394,10 +445,6 @@
|
|
|
394
445
|
- projection: configure map projection
|
|
395
446
|
- legend:
|
|
396
447
|
- embeded: deactivate mouse scroll
|
|
397
|
-
- marker: offset, size, ...
|
|
398
|
-
- load markers from file
|
|
399
|
-
- load data from file
|
|
400
|
-
|
|
401
448
|
-->
|
|
402
449
|
</body>
|
|
403
450
|
</html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.1.0-dev.
|
|
1
|
+
{"version":"1.1.0-dev.2557861681", "build":"2557861681", "date":"28/05/2026"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
id point title description icon iconSize iconOffset
|
|
2
|
+
1 1146337,2554168 Information Office de l'information<br />Tél: 032 000 00 00<br>Email: <a href="mailto:info@example.com">info@example.com</a><br />Internet: <a href="http://fr.wikipedia.org/wiki/La_Chaux-de-Fonds" target=new>Cliquer ici</a> api/marker-plus.png 21,25 -51,-90
|
|
3
|
+
2 1146205,2554168 Ma première station Diesel pas cher api/marker2-plus.png 21,25 -51,-90
|
|
4
|
+
3 1145605,2554168 Mon parking C'est celui-là le meilleur. api/marker2-plus.png 21,25 -51,-90
|
|
5
|
+
4 1145542,2554168 Mon parking Ce parking est<br/>le meillleur. api/marker2-plus.png 21,25 -51,-90
|
|
6
|
+
5 1145977,2554168 Ma deuxième station Sans-plomb pas cher. api/marker-plus.png 21,25 -51,-90
|
|
7
|
+
6 1145631,2554175 Test marker 1. api/marker-plus.png 21,25 -51,-90
|
|
8
|
+
7 1145472,2554507 Test marker 2. api/marker2-plus.png 21,25 -51,-90
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
id point title description icon iconSize iconOffset
|
|
2
|
+
1 2611778,1266865 Popups konfigurieren <br>Popups können via der Text-Datei beliebig mit Inhalt gefüllt werden!<br/>Die anderen zwei Beispiel-Popups zeigen weitere Beispiele.<br><img src="/static/api/apihelp/img/geoportal-bs.jpg" width="300px"> api/marker-blue.png 21,25 -10.5,-25
|
|
3
|
+
2 2611542,1267266 Klänge der Basler Fasnacht <br/><br/>Audio-Dateien in ein Popup einbinden:<br/><br/><audio controls><source src="/static/api/apihelp/BS_N19_Fasnacht_v1.mp3" type="audio/mp3">Your browser does not support the audio element.</audio> api/marker-green.png 21,25 -10.5,-25
|
|
4
|
+
3 2613089,1267566 FILM AB! Für den GEO-Beruf <br>IFrames in ein Popup einbinden: <br/><br/><iframe width="312" height="175" src="https://www.youtube.com/embed/-Mw277Rgcyc" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> api/parking.png 21,25 -10.5,-25
|
|
5
|
+
4 2611738,1267123 Test for Offset/Size Test for Offset/Size api/marker-huge.png 24,38 -162,-512
|
|
6
|
+
5 2611738,1267123 Test for Offset/Size Test for Offset/Size api/marker-huge.png 24,38 -12,-38
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/tools/main.d.ts
CHANGED
|
@@ -120,7 +120,7 @@ export { unByKeyAll, getOlayerByName, removeUnwantedOlParams, polygonFromCircle,
|
|
|
120
120
|
export { getPropertyByPath, setPropertyByPath, createObjectFromPath, deletePropertyByPath, mergeObjects } from './utils/pathUtils.js';
|
|
121
121
|
export { generateQrCode } from './utils/qrcode.js';
|
|
122
122
|
export { default as ServiceWorkerHelper } from './utils/swhelper.js';
|
|
123
|
-
export { systemIsInDarkMode, isSafari, isFirefox, getValidIndex, minMax, hexToRgbaArray, rgbStrToRgbaArray, colorToRgbaArray, isValidEmail, applyOpacityToLayers, applyFeaturesToSelection, linkify, applyDefaultPrefixToUrl } from './utils/utils.js';
|
|
123
|
+
export { systemIsInDarkMode, isSafari, isFirefox, getValidIndex, minMax, hexToRgbaArray, rgbStrToRgbaArray, colorToRgbaArray, isValidEmail, applyOpacityToLayers, applyFeaturesToSelection, linkify, applyDefaultPrefixToUrl, splitTrimAndConvertToNumber } from './utils/utils.js';
|
|
124
124
|
export { default as VendorSpecificOgcServerManager } from './vendorspecificogcservermanager.js';
|
|
125
125
|
export type { WfsClientOptions, WfsClientOptionalOptions, QueryableLayerWms, GetFeatureOptionsPartial } from './wfs/wfsclient.js';
|
|
126
126
|
export { default as WfsClient, WfsClientMapServer, WfsClientQgis, WfsClientGeorama, WfsClientDefault, WfsClientGeoServer } from './wfs/wfsclient.js';
|
package/tools/main.js
CHANGED
|
@@ -94,7 +94,7 @@ export { unByKeyAll, getOlayerByName, removeUnwantedOlParams, polygonFromCircle,
|
|
|
94
94
|
export { getPropertyByPath, setPropertyByPath, createObjectFromPath, deletePropertyByPath, mergeObjects } from './utils/pathUtils.js';
|
|
95
95
|
export { generateQrCode } from './utils/qrcode.js';
|
|
96
96
|
export { default as ServiceWorkerHelper } from './utils/swhelper.js';
|
|
97
|
-
export { systemIsInDarkMode, isSafari, isFirefox, getValidIndex, minMax, hexToRgbaArray, rgbStrToRgbaArray, colorToRgbaArray, isValidEmail, applyOpacityToLayers, applyFeaturesToSelection, linkify, applyDefaultPrefixToUrl } from './utils/utils.js';
|
|
97
|
+
export { systemIsInDarkMode, isSafari, isFirefox, getValidIndex, minMax, hexToRgbaArray, rgbStrToRgbaArray, colorToRgbaArray, isValidEmail, applyOpacityToLayers, applyFeaturesToSelection, linkify, applyDefaultPrefixToUrl, splitTrimAndConvertToNumber } from './utils/utils.js';
|
|
98
98
|
export { default as VendorSpecificOgcServerManager } from './vendorspecificogcservermanager.js';
|
|
99
99
|
export { default as WfsClient, WfsClientMapServer, WfsClientQgis, WfsClientGeorama, WfsClientDefault, WfsClientGeoServer } from './wfs/wfsclient.js';
|
|
100
100
|
export { default as WfsFilter } from './wfs/wfsfilter.js';
|
|
@@ -21,7 +21,12 @@ export default class PermalinkManager extends GirafeSingleton {
|
|
|
21
21
|
hasMapPosition(): boolean | "" | null;
|
|
22
22
|
private hasToolTip;
|
|
23
23
|
private hasMarker;
|
|
24
|
+
private hasMarkerSize;
|
|
25
|
+
private hasMarkerOffset;
|
|
24
26
|
getMapPosition(targetProjection: Projection): MapPosition | undefined;
|
|
27
|
+
private addCenter;
|
|
28
|
+
private addTooltip;
|
|
29
|
+
private addMarker;
|
|
25
30
|
hasSearch(): boolean;
|
|
26
31
|
getSearchTerm(): string;
|
|
27
32
|
hasThemes(): boolean;
|
|
@@ -5,6 +5,7 @@ import MapPosition from '../state/mapposition.js';
|
|
|
5
5
|
import { get as getProjection, transform } from 'ol/proj.js';
|
|
6
6
|
import { isCoordinateInDegrees } from '../utils/olutils.js';
|
|
7
7
|
import { BASEMAP_VISIBLE_PARAMETER, SEARCH_VISIBLE_PARAMETER } from './permalinkmanager-constants.js';
|
|
8
|
+
import { splitTrimAndConvertToNumber } from '../utils/utils.js';
|
|
8
9
|
export default class PermalinkManager extends GirafeSingleton {
|
|
9
10
|
urlParamKeys = [
|
|
10
11
|
'map_x',
|
|
@@ -13,6 +14,8 @@ export default class PermalinkManager extends GirafeSingleton {
|
|
|
13
14
|
'map_crosshair',
|
|
14
15
|
'map_tooltip',
|
|
15
16
|
'map_marker',
|
|
17
|
+
'map_marker_size',
|
|
18
|
+
'map_marker_offset',
|
|
16
19
|
'search',
|
|
17
20
|
'basemap',
|
|
18
21
|
'themes',
|
|
@@ -83,46 +86,71 @@ export default class PermalinkManager extends GirafeSingleton {
|
|
|
83
86
|
hasMarker() {
|
|
84
87
|
return this.params['map_marker'] !== null;
|
|
85
88
|
}
|
|
89
|
+
hasMarkerSize() {
|
|
90
|
+
return this.params['map_marker_size'] !== null;
|
|
91
|
+
}
|
|
92
|
+
hasMarkerOffset() {
|
|
93
|
+
return this.params['map_marker_offset'] !== null;
|
|
94
|
+
}
|
|
86
95
|
getMapPosition(targetProjection) {
|
|
87
96
|
if (this.hasMapPosition()) {
|
|
88
97
|
const position = new MapPosition();
|
|
89
|
-
|
|
90
|
-
// Transform position to the target projection by making an educated guess about the current CRS
|
|
91
|
-
// of the permalink map position
|
|
92
|
-
const defaultProjection = this.context.configManager.getDefaultConfigValue('map.srid');
|
|
93
|
-
const projectionInUrl = getProjection(isCoordinateInDegrees(position.center) ? 'EPSG:4326' : defaultProjection);
|
|
94
|
-
if (projectionInUrl.getCode() !== this.state.projection) {
|
|
95
|
-
center = transform(center, projectionInUrl, targetProjection);
|
|
96
|
-
}
|
|
97
|
-
position.center = center;
|
|
98
|
+
this.addCenter(position, targetProjection);
|
|
98
99
|
const defaultZoom = this.context.configManager.getDefaultConfigValue('map.startZoom');
|
|
99
100
|
position.zoom = Number.parseInt(this.params['map_zoom'] ?? defaultZoom);
|
|
100
101
|
if (this.params['map_crosshair'] === 'true') {
|
|
101
|
-
position.crosshair = center;
|
|
102
|
-
}
|
|
103
|
-
if (this.hasToolTip()) {
|
|
104
|
-
const content = DOMPurify.sanitize(this.params['map_tooltip'], {
|
|
105
|
-
ALLOWED_TAGS: ['br', 'b', 'div', 'em', 'i', 'p', 'strong'],
|
|
106
|
-
ALLOWED_ATTR: []
|
|
107
|
-
});
|
|
108
|
-
position.tooltip = {
|
|
109
|
-
content: content,
|
|
110
|
-
position: center
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
if (this.hasMarker()) {
|
|
114
|
-
const imageUrl = DOMPurify.sanitize(this.params['map_marker']);
|
|
115
|
-
position.markers.push({
|
|
116
|
-
imageUrl: imageUrl,
|
|
117
|
-
position: center
|
|
118
|
-
});
|
|
102
|
+
position.crosshair = position.center;
|
|
119
103
|
}
|
|
104
|
+
this.addTooltip(position);
|
|
105
|
+
this.addMarker(position);
|
|
120
106
|
if (position.isValid) {
|
|
121
107
|
return position;
|
|
122
108
|
}
|
|
123
109
|
}
|
|
124
110
|
return undefined;
|
|
125
111
|
}
|
|
112
|
+
addCenter(position, targetProjection) {
|
|
113
|
+
let center = [Number.parseFloat(this.params['map_x']), Number.parseFloat(this.params['map_y'])];
|
|
114
|
+
// Transform position to the target projection by making an educated guess about the current CRS
|
|
115
|
+
// of the permalink map position
|
|
116
|
+
const defaultProjection = this.context.configManager.getDefaultConfigValue('map.srid');
|
|
117
|
+
const projectionInUrl = getProjection(isCoordinateInDegrees(position.center) ? 'EPSG:4326' : defaultProjection);
|
|
118
|
+
if (projectionInUrl.getCode() !== this.state.projection) {
|
|
119
|
+
center = transform(center, projectionInUrl, targetProjection);
|
|
120
|
+
}
|
|
121
|
+
position.center = center;
|
|
122
|
+
}
|
|
123
|
+
addTooltip(position) {
|
|
124
|
+
if (this.hasToolTip()) {
|
|
125
|
+
const content = DOMPurify.sanitize(this.params['map_tooltip'], {
|
|
126
|
+
ALLOWED_TAGS: ['br', 'b', 'div', 'em', 'i', 'p', 'strong'],
|
|
127
|
+
ALLOWED_ATTR: []
|
|
128
|
+
});
|
|
129
|
+
position.tooltip = {
|
|
130
|
+
content: content,
|
|
131
|
+
position: position.center
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
addMarker(position) {
|
|
136
|
+
if (this.hasMarker()) {
|
|
137
|
+
const imageUrl = DOMPurify.sanitize(this.params['map_marker']);
|
|
138
|
+
let size;
|
|
139
|
+
let offset;
|
|
140
|
+
if (this.hasMarkerSize()) {
|
|
141
|
+
size = splitTrimAndConvertToNumber(DOMPurify.sanitize(this.params['map_marker_size']));
|
|
142
|
+
}
|
|
143
|
+
if (this.hasMarkerOffset()) {
|
|
144
|
+
offset = splitTrimAndConvertToNumber(DOMPurify.sanitize(this.params['map_marker_offset']));
|
|
145
|
+
}
|
|
146
|
+
position.markers.push({
|
|
147
|
+
imageUrl: imageUrl,
|
|
148
|
+
position: position.center,
|
|
149
|
+
size: size,
|
|
150
|
+
offset: offset
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
126
154
|
hasSearch() {
|
|
127
155
|
return this.params['search'] !== null;
|
|
128
156
|
}
|
package/tools/utils/utils.d.ts
CHANGED
|
@@ -77,3 +77,8 @@ export declare const linkify: (str: string) => string;
|
|
|
77
77
|
* @returns
|
|
78
78
|
*/
|
|
79
79
|
export declare function applyDefaultPrefixToUrl(context: IGirafeContext, metadataUrl?: string): string | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Splits a String containing Numbers into an Array of Numbers. The Separator is a comma.
|
|
82
|
+
* @param numbersAsString The String containing Numbers.
|
|
83
|
+
*/
|
|
84
|
+
export declare const splitTrimAndConvertToNumber: (numbersAsString: string) => number[];
|
package/tools/utils/utils.js
CHANGED
|
@@ -199,3 +199,13 @@ export function applyDefaultPrefixToUrl(context, metadataUrl) {
|
|
|
199
199
|
}
|
|
200
200
|
return metadataUrl;
|
|
201
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Splits a String containing Numbers into an Array of Numbers. The Separator is a comma.
|
|
204
|
+
* @param numbersAsString The String containing Numbers.
|
|
205
|
+
*/
|
|
206
|
+
export const splitTrimAndConvertToNumber = (numbersAsString) => {
|
|
207
|
+
return numbersAsString
|
|
208
|
+
.split(',')
|
|
209
|
+
.map((e) => e.trim())
|
|
210
|
+
.map(Number);
|
|
211
|
+
};
|