@orbat-mapper/tactical-draw-adapter-maplibre 0.2.0-alpha.7 → 0.2.0-alpha.9
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 +13 -2
- package/dist/index.mjs +87 -22
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -13,10 +13,20 @@ type MapLibreEventToken = (e: any) => void;
|
|
|
13
13
|
interface MapLibreViewToken {
|
|
14
14
|
fn: () => void;
|
|
15
15
|
}
|
|
16
|
+
interface MapLibreAdapterOptions {
|
|
17
|
+
/**
|
|
18
|
+
* How view changes propagate to view-state refits. "continuous" (default)
|
|
19
|
+
* refits on every frame of an animated zoom/rotate/pitch; "settle" defers
|
|
20
|
+
* the refit until the animation ends.
|
|
21
|
+
*/
|
|
22
|
+
viewChangeMode?: "continuous" | "settle";
|
|
23
|
+
}
|
|
16
24
|
declare class MapLibreAdapter extends BaseMapAdapter<MapLibreLayerHandle, MapLibreEventToken, MapLibreViewToken> {
|
|
17
25
|
private map;
|
|
26
|
+
private readonly viewChangeMode;
|
|
18
27
|
private readonly pendingIconImages;
|
|
19
|
-
|
|
28
|
+
readonly scalesGroundPointSymbolsNatively = true;
|
|
29
|
+
constructor(map: maplibregl.Map, options?: MapLibreAdapterOptions);
|
|
20
30
|
private toContinuousLng;
|
|
21
31
|
protected createLayer(layerId: LayerId, style?: StyleOptions): MapLibreLayerHandle;
|
|
22
32
|
protected destroyLayer(handle: MapLibreLayerHandle): void;
|
|
@@ -27,6 +37,7 @@ declare class MapLibreAdapter extends BaseMapAdapter<MapLibreLayerHandle, MapLib
|
|
|
27
37
|
protected detachNativeEvent(entry: NativeEventEntry<MapLibreEventToken>): void;
|
|
28
38
|
protected attachViewChange(handler: () => void): MapLibreViewToken;
|
|
29
39
|
protected detachViewChange(token: MapLibreViewToken): void;
|
|
40
|
+
private viewChangeEvents;
|
|
30
41
|
createEditPointerDriver(): EditPointerDriver;
|
|
31
42
|
setLayerStyle(layerId: LayerId, style: StyleOptions): void;
|
|
32
43
|
toLonLat(coordinate: number[]): Position;
|
|
@@ -48,4 +59,4 @@ declare class MapLibreAdapter extends BaseMapAdapter<MapLibreLayerHandle, MapLib
|
|
|
48
59
|
setGlobeMode(enabled: boolean): void;
|
|
49
60
|
}
|
|
50
61
|
//#endregion
|
|
51
|
-
export { MapLibreAdapter };
|
|
62
|
+
export { MapLibreAdapter, type MapLibreAdapterOptions };
|
package/dist/index.mjs
CHANGED
|
@@ -80,11 +80,7 @@ function buildIconLayer(id, source) {
|
|
|
80
80
|
],
|
|
81
81
|
layout: {
|
|
82
82
|
"icon-image": ["get", "iconId"],
|
|
83
|
-
"icon-size":
|
|
84
|
-
"coalesce",
|
|
85
|
-
["get", "iconScale"],
|
|
86
|
-
1
|
|
87
|
-
],
|
|
83
|
+
"icon-size": buildIconSizeExpression(),
|
|
88
84
|
"icon-rotate": [
|
|
89
85
|
"*",
|
|
90
86
|
[
|
|
@@ -162,6 +158,60 @@ function buildTextSizeExpression(text) {
|
|
|
162
158
|
];
|
|
163
159
|
}
|
|
164
160
|
/**
|
|
161
|
+
* Per-feature icon size, same zoom-stop scheme as `buildTextSizeExpression`:
|
|
162
|
+
* a ground-sized point symbol carries `iconSizeMeters`/`iconOctagonSize` (and
|
|
163
|
+
* optional `iconMinPixels`/`iconMaxPixels`), so the meters→pixels clamp is
|
|
164
|
+
* evaluated inside the style layer at every integer zoom stop and the symbol
|
|
165
|
+
* scales smoothly through animated zooms. Anything else falls back to the
|
|
166
|
+
* host-computed `iconScale` snapshot.
|
|
167
|
+
*/
|
|
168
|
+
function buildIconSizeExpression() {
|
|
169
|
+
const minExpr = [
|
|
170
|
+
"coalesce",
|
|
171
|
+
["get", "iconMinPixels"],
|
|
172
|
+
0
|
|
173
|
+
];
|
|
174
|
+
const maxExpr = [
|
|
175
|
+
"coalesce",
|
|
176
|
+
["get", "iconMaxPixels"],
|
|
177
|
+
1e9
|
|
178
|
+
];
|
|
179
|
+
const scaleAtZoom = (zoom) => {
|
|
180
|
+
return [
|
|
181
|
+
"case",
|
|
182
|
+
["has", "iconSizeMeters"],
|
|
183
|
+
[
|
|
184
|
+
"/",
|
|
185
|
+
[
|
|
186
|
+
"max",
|
|
187
|
+
minExpr,
|
|
188
|
+
[
|
|
189
|
+
"min",
|
|
190
|
+
maxExpr,
|
|
191
|
+
[
|
|
192
|
+
"*",
|
|
193
|
+
["get", "iconSizeMeters"],
|
|
194
|
+
Math.pow(2, zoom + 9) / WEB_MERCATOR_CIRCUMFERENCE
|
|
195
|
+
]
|
|
196
|
+
]
|
|
197
|
+
],
|
|
198
|
+
["get", "iconOctagonSize"]
|
|
199
|
+
],
|
|
200
|
+
[
|
|
201
|
+
"coalesce",
|
|
202
|
+
["get", "iconScale"],
|
|
203
|
+
1
|
|
204
|
+
]
|
|
205
|
+
];
|
|
206
|
+
};
|
|
207
|
+
return [
|
|
208
|
+
"interpolate",
|
|
209
|
+
["linear"],
|
|
210
|
+
["zoom"],
|
|
211
|
+
...Array.from({ length: 25 }, (_, zoom) => [zoom, scaleAtZoom(zoom)]).flat()
|
|
212
|
+
];
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
165
215
|
* Build the paint expression for a fill layer with per-feature
|
|
166
216
|
* `properties.style.fillColor` overlay. Mirrors `buildCirclePaint`.
|
|
167
217
|
*/
|
|
@@ -287,10 +337,13 @@ function buildLinePaint(style) {
|
|
|
287
337
|
}
|
|
288
338
|
var MapLibreAdapter = class extends BaseMapAdapter {
|
|
289
339
|
map;
|
|
340
|
+
viewChangeMode;
|
|
290
341
|
pendingIconImages = /* @__PURE__ */ new Set();
|
|
291
|
-
|
|
342
|
+
scalesGroundPointSymbolsNatively = true;
|
|
343
|
+
constructor(map, options = {}) {
|
|
292
344
|
super();
|
|
293
345
|
this.map = map;
|
|
346
|
+
this.viewChangeMode = options.viewChangeMode ?? "continuous";
|
|
294
347
|
}
|
|
295
348
|
toContinuousLng(lng) {
|
|
296
349
|
return nearestWorldCopyLng(lng, this.map.getCenter().lng);
|
|
@@ -420,17 +473,19 @@ var MapLibreAdapter = class extends BaseMapAdapter {
|
|
|
420
473
|
}
|
|
421
474
|
attachViewChange(handler) {
|
|
422
475
|
const fn = () => handler();
|
|
423
|
-
this.map.on(
|
|
424
|
-
this.map.on("rotate", fn);
|
|
425
|
-
this.map.on("pitch", fn);
|
|
426
|
-
this.map.on("moveend", fn);
|
|
476
|
+
for (const event of this.viewChangeEvents()) this.map.on(event, fn);
|
|
427
477
|
return { fn };
|
|
428
478
|
}
|
|
429
479
|
detachViewChange(token) {
|
|
430
|
-
this.map.off(
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
this.
|
|
480
|
+
for (const event of this.viewChangeEvents()) this.map.off(event, token.fn);
|
|
481
|
+
}
|
|
482
|
+
viewChangeEvents() {
|
|
483
|
+
return this.viewChangeMode === "settle" ? ["moveend"] : [
|
|
484
|
+
"zoom",
|
|
485
|
+
"rotate",
|
|
486
|
+
"pitch",
|
|
487
|
+
"moveend"
|
|
488
|
+
];
|
|
434
489
|
}
|
|
435
490
|
createEditPointerDriver() {
|
|
436
491
|
const map = this.map;
|
|
@@ -440,7 +495,10 @@ var MapLibreAdapter = class extends BaseMapAdapter {
|
|
|
440
495
|
let disposed = false;
|
|
441
496
|
let touchDragActive = false;
|
|
442
497
|
let multiTouchCancelled = false;
|
|
443
|
-
const
|
|
498
|
+
const touchInfo = (e) => ({
|
|
499
|
+
hitTolerance: TOUCH_HIT_TOLERANCE_PX,
|
|
500
|
+
native: e.originalEvent
|
|
501
|
+
});
|
|
444
502
|
const preventMapEventDefaults = (e) => {
|
|
445
503
|
e.preventDefault();
|
|
446
504
|
e.originalEvent.preventDefault?.();
|
|
@@ -450,23 +508,30 @@ var MapLibreAdapter = class extends BaseMapAdapter {
|
|
|
450
508
|
const px = [e.point.x, e.point.y];
|
|
451
509
|
const info = {
|
|
452
510
|
altKey: e.originalEvent.altKey,
|
|
453
|
-
shiftKey: e.originalEvent.shiftKey
|
|
511
|
+
shiftKey: e.originalEvent.shiftKey,
|
|
512
|
+
native: e.originalEvent
|
|
454
513
|
};
|
|
455
514
|
hub.fireDown(px, info);
|
|
456
515
|
};
|
|
457
516
|
const onMove = (e) => {
|
|
458
517
|
const px = [e.point.x, e.point.y];
|
|
459
|
-
hub.fireMove(px, {
|
|
518
|
+
hub.fireMove(px, {
|
|
519
|
+
shiftKey: e.originalEvent.shiftKey,
|
|
520
|
+
native: e.originalEvent
|
|
521
|
+
});
|
|
460
522
|
};
|
|
461
523
|
const onUp = (e) => {
|
|
462
524
|
const px = [e.point.x, e.point.y];
|
|
463
|
-
hub.fireUp(px, {
|
|
525
|
+
hub.fireUp(px, {
|
|
526
|
+
shiftKey: e.originalEvent.shiftKey,
|
|
527
|
+
native: e.originalEvent
|
|
528
|
+
});
|
|
464
529
|
};
|
|
465
530
|
const onTouchStart = (e) => {
|
|
466
531
|
if (e.points.length !== 1) return;
|
|
467
532
|
const before = dragPanWasEnabled;
|
|
468
533
|
const px = [e.point.x, e.point.y];
|
|
469
|
-
hub.fireDown(px,
|
|
534
|
+
hub.fireDown(px, touchInfo(e));
|
|
470
535
|
touchDragActive = dragPanWasEnabled !== before;
|
|
471
536
|
if (touchDragActive) preventMapEventDefaults(e);
|
|
472
537
|
};
|
|
@@ -475,20 +540,20 @@ var MapLibreAdapter = class extends BaseMapAdapter {
|
|
|
475
540
|
const px = [e.point.x, e.point.y];
|
|
476
541
|
if (touchCount > 1 && touchDragActive && !multiTouchCancelled) {
|
|
477
542
|
multiTouchCancelled = true;
|
|
478
|
-
hub.fireUp(px,
|
|
543
|
+
hub.fireUp(px, touchInfo(e));
|
|
479
544
|
touchDragActive = false;
|
|
480
545
|
preventMapEventDefaults(e);
|
|
481
546
|
return;
|
|
482
547
|
}
|
|
483
548
|
if (touchCount > 1) return;
|
|
484
549
|
if (touchCount === 1) multiTouchCancelled = false;
|
|
485
|
-
hub.fireMove(px,
|
|
550
|
+
hub.fireMove(px, touchInfo(e));
|
|
486
551
|
if (touchDragActive) preventMapEventDefaults(e);
|
|
487
552
|
};
|
|
488
553
|
const onTouchEnd = (e) => {
|
|
489
554
|
multiTouchCancelled = false;
|
|
490
555
|
const px = [e.point.x, e.point.y];
|
|
491
|
-
hub.fireUp(px,
|
|
556
|
+
hub.fireUp(px, touchInfo(e));
|
|
492
557
|
touchDragActive = false;
|
|
493
558
|
};
|
|
494
559
|
map.on("mousedown", onDown);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orbat-mapper/tactical-draw-adapter-maplibre",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.9",
|
|
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",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@orbat-mapper/control-measures": "^0.2.0-alpha.15",
|
|
41
|
-
"@orbat-mapper/tactical-draw": "^0.2.0-alpha.
|
|
41
|
+
"@orbat-mapper/tactical-draw": "^0.2.0-alpha.24"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"maplibre-gl": ">=4.0.0 <6.0.0"
|