@orbat-mapper/tactical-draw-adapter-maplibre 0.2.0 → 0.2.2
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/dist/index.d.mts +14 -0
- package/dist/index.mjs +82 -5
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -32,6 +32,19 @@ interface MapLibreGroupBundle {
|
|
|
32
32
|
*/
|
|
33
33
|
revision?: number;
|
|
34
34
|
requiredIconIds: ReadonlySet<string>;
|
|
35
|
+
overlays: Map<string, MapLibreImageOverlayHandle>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Last-applied scalar state for a rendered image overlay, used to skip
|
|
39
|
+
* MapLibre's `ImageSource.updateImage` (which re-fetches and re-decodes the
|
|
40
|
+
* raster) whenever nothing but the position changed.
|
|
41
|
+
*/
|
|
42
|
+
interface MapLibreImageOverlayHandle {
|
|
43
|
+
sourceId: string;
|
|
44
|
+
layerId: string;
|
|
45
|
+
url: string;
|
|
46
|
+
opacity: number;
|
|
47
|
+
coordinates: readonly [Position, Position, Position, Position];
|
|
35
48
|
}
|
|
36
49
|
type MapLibreEventToken = (e: any) => void;
|
|
37
50
|
interface MapLibreViewToken {
|
|
@@ -57,6 +70,7 @@ declare class MapLibreAdapter extends BaseMapAdapter<MapLibreLayerHandle, MapLib
|
|
|
57
70
|
protected applyFeatureGroups(layerId: LayerId, groups: readonly FeatureGroup[]): void;
|
|
58
71
|
private createGroupBundle;
|
|
59
72
|
private destroyGroupBundle;
|
|
73
|
+
private reconcileGroupImageOverlays;
|
|
60
74
|
private clearGroupBundles;
|
|
61
75
|
private requiredIconIds;
|
|
62
76
|
private reconcileGroupChannels;
|
package/dist/index.mjs
CHANGED
|
@@ -8,6 +8,14 @@ const DEFAULT_LINE_WIDTH = 2;
|
|
|
8
8
|
function isHatchPattern(value) {
|
|
9
9
|
return HATCH_PATTERNS.includes(value);
|
|
10
10
|
}
|
|
11
|
+
function coordinatesEqual(a, b) {
|
|
12
|
+
for (let index = 0; index < 4; index++) {
|
|
13
|
+
const pa = a[index];
|
|
14
|
+
const pb = b[index];
|
|
15
|
+
if (pa[0] !== pb[0] || pa[1] !== pb[1]) return false;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
11
19
|
const PAINT_CHANNELS = [
|
|
12
20
|
"fill",
|
|
13
21
|
"fill-pattern",
|
|
@@ -17,6 +25,7 @@ const PAINT_CHANNELS = [
|
|
|
17
25
|
"text"
|
|
18
26
|
];
|
|
19
27
|
function firstBundleLayerId(bundle) {
|
|
28
|
+
for (const overlay of bundle.overlays.values()) return overlay.layerId;
|
|
20
29
|
for (const channel of PAINT_CHANNELS) {
|
|
21
30
|
const layerId = bundle.layerIds.get(channel);
|
|
22
31
|
if (layerId) return layerId;
|
|
@@ -907,6 +916,7 @@ var MapLibreAdapter = class extends BaseMapAdapter {
|
|
|
907
916
|
bundle.features = group.features;
|
|
908
917
|
bundle.revision = group.revision;
|
|
909
918
|
bundle.requiredIconIds = requiredIconIds;
|
|
919
|
+
if (this.reconcileGroupImageOverlays(handle, bundle, group.imageOverlays ?? [])) bundlesNeedingOrder.add(group.id);
|
|
910
920
|
if (this.reconcileGroupChannels(handle, bundle, groupPaintChannels(group.features, handle.style))) bundlesNeedingOrder.add(group.id);
|
|
911
921
|
if (contentChanged || resourcesChanged) this.updateGroupBundleSource(bundle);
|
|
912
922
|
}
|
|
@@ -927,13 +937,73 @@ var MapLibreAdapter = class extends BaseMapAdapter {
|
|
|
927
937
|
sourceFeatures: [],
|
|
928
938
|
sourceInitialized: false,
|
|
929
939
|
featureSignature: "[]",
|
|
930
|
-
requiredIconIds: /* @__PURE__ */ new Set()
|
|
940
|
+
requiredIconIds: /* @__PURE__ */ new Set(),
|
|
941
|
+
overlays: /* @__PURE__ */ new Map()
|
|
931
942
|
};
|
|
932
943
|
}
|
|
933
944
|
destroyGroupBundle(bundle) {
|
|
945
|
+
for (const overlay of bundle.overlays.values()) {
|
|
946
|
+
if (this.map.getLayer(overlay.layerId)) this.map.removeLayer(overlay.layerId);
|
|
947
|
+
if (this.map.getSource(overlay.sourceId)) this.map.removeSource(overlay.sourceId);
|
|
948
|
+
}
|
|
934
949
|
for (const layerId of bundle.layerIds.values()) if (this.map.getLayer(layerId)) this.map.removeLayer(layerId);
|
|
935
950
|
if (this.map.getSource(bundle.sourceId)) this.map.removeSource(bundle.sourceId);
|
|
936
951
|
}
|
|
952
|
+
reconcileGroupImageOverlays(handle, bundle, overlays) {
|
|
953
|
+
let structureChanged = false;
|
|
954
|
+
const desiredIds = new Set(overlays.map((overlay) => overlay.id));
|
|
955
|
+
for (const [id, native] of bundle.overlays) {
|
|
956
|
+
if (desiredIds.has(id)) continue;
|
|
957
|
+
if (this.map.getLayer(native.layerId)) this.map.removeLayer(native.layerId);
|
|
958
|
+
if (this.map.getSource(native.sourceId)) this.map.removeSource(native.sourceId);
|
|
959
|
+
bundle.overlays.delete(id);
|
|
960
|
+
structureChanged = true;
|
|
961
|
+
}
|
|
962
|
+
for (const overlay of overlays) {
|
|
963
|
+
const existing = bundle.overlays.get(overlay.id);
|
|
964
|
+
const url = overlay.url;
|
|
965
|
+
if (!existing) {
|
|
966
|
+
const suffix = `${bundle.sourceId}-${encodeURIComponent(overlay.id)}`;
|
|
967
|
+
const sourceId = `${suffix}-image-src`;
|
|
968
|
+
const layerId = `${suffix}-image`;
|
|
969
|
+
this.map.addSource(sourceId, {
|
|
970
|
+
type: "image",
|
|
971
|
+
url,
|
|
972
|
+
coordinates: overlay.coordinates
|
|
973
|
+
});
|
|
974
|
+
this.map.addLayer({
|
|
975
|
+
id: layerId,
|
|
976
|
+
type: "raster",
|
|
977
|
+
source: sourceId,
|
|
978
|
+
paint: { "raster-opacity": overlay.opacity }
|
|
979
|
+
}, handle.mlLayerIds[0]);
|
|
980
|
+
bundle.overlays.set(overlay.id, {
|
|
981
|
+
sourceId,
|
|
982
|
+
layerId,
|
|
983
|
+
url,
|
|
984
|
+
opacity: overlay.opacity,
|
|
985
|
+
coordinates: overlay.coordinates
|
|
986
|
+
});
|
|
987
|
+
structureChanged = true;
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
const urlChanged = existing.url !== url;
|
|
991
|
+
const coordinatesChanged = !coordinatesEqual(existing.coordinates, overlay.coordinates);
|
|
992
|
+
const opacityChanged = existing.opacity !== overlay.opacity;
|
|
993
|
+
if (!urlChanged && !coordinatesChanged && !opacityChanged) continue;
|
|
994
|
+
const source = this.map.getSource(existing.sourceId);
|
|
995
|
+
if (urlChanged) source?.updateImage?.({
|
|
996
|
+
url,
|
|
997
|
+
coordinates: overlay.coordinates.map((point) => [...point])
|
|
998
|
+
});
|
|
999
|
+
else if (coordinatesChanged) source?.setCoordinates?.(overlay.coordinates.map((point) => [...point]));
|
|
1000
|
+
if (opacityChanged) this.map.setPaintProperty(existing.layerId, "raster-opacity", overlay.opacity);
|
|
1001
|
+
existing.url = url;
|
|
1002
|
+
existing.opacity = overlay.opacity;
|
|
1003
|
+
existing.coordinates = overlay.coordinates;
|
|
1004
|
+
}
|
|
1005
|
+
return structureChanged;
|
|
1006
|
+
}
|
|
937
1007
|
clearGroupBundles(handle) {
|
|
938
1008
|
for (const bundle of handle.groupBundles.values()) this.destroyGroupBundle(bundle);
|
|
939
1009
|
handle.groupBundles.clear();
|
|
@@ -1035,15 +1105,22 @@ var MapLibreAdapter = class extends BaseMapAdapter {
|
|
|
1035
1105
|
const groupId = desiredGroupIds[index];
|
|
1036
1106
|
const bundle = handle.groupBundles.get(groupId);
|
|
1037
1107
|
if (!bundle) continue;
|
|
1038
|
-
if (forcedGroupIds.has(groupId) || stableGroupIds !== null && !stableGroupIds.has(groupId))
|
|
1039
|
-
const
|
|
1040
|
-
|
|
1108
|
+
if (forcedGroupIds.has(groupId) || stableGroupIds !== null && !stableGroupIds.has(groupId)) {
|
|
1109
|
+
for (const overlay of bundle.overlays.values()) if (this.map.getLayer(overlay.layerId)) this.map.moveLayer(overlay.layerId, beforeId);
|
|
1110
|
+
for (const channel of PAINT_CHANNELS) {
|
|
1111
|
+
const layerId = bundle.layerIds.get(channel);
|
|
1112
|
+
if (layerId && this.map.getLayer(layerId)) this.map.moveLayer(layerId, beforeId);
|
|
1113
|
+
}
|
|
1041
1114
|
}
|
|
1042
1115
|
beforeId = firstBundleLayerId(bundle) ?? beforeId;
|
|
1043
1116
|
}
|
|
1044
1117
|
}
|
|
1045
1118
|
nativeLayerIds(handle) {
|
|
1046
|
-
return [
|
|
1119
|
+
return [
|
|
1120
|
+
...handle.mlLayerIds,
|
|
1121
|
+
...[...handle.groupBundles.values()].flatMap((bundle) => [...bundle.layerIds.values()]),
|
|
1122
|
+
...[...handle.groupBundles.values()].flatMap((bundle) => [...bundle.overlays.values()].map((overlay) => overlay.layerId))
|
|
1123
|
+
];
|
|
1047
1124
|
}
|
|
1048
1125
|
/**
|
|
1049
1126
|
* Promote a source feature for MapLibre: stamp `_fid` (so data-driven paint
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orbat-mapper/tactical-draw-adapter-maplibre",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "MapLibre GL JS engine adapter for @orbat-mapper/tactical-draw. Draw and edit tactical control measures (MIL-STD-2525 / APP-6) on a MapLibre map.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Orbat Mapper",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@orbat-mapper/control-measures": "^0.
|
|
41
|
-
"@orbat-mapper/tactical-draw": "^0.
|
|
40
|
+
"@orbat-mapper/control-measures": "^0.3.1",
|
|
41
|
+
"@orbat-mapper/tactical-draw": "^0.3.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"maplibre-gl": ">=5.8.0 <6.0.0"
|