@orbat-mapper/tactical-draw 0.2.0-alpha.12 → 0.2.0-alpha.14
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 +39 -9
- package/dist/index.mjs +111 -40
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -57,9 +57,12 @@ interface StyleOptions {
|
|
|
57
57
|
/**
|
|
58
58
|
* Text (label) style for a layer. When `labelProperty` is set, adapters also
|
|
59
59
|
* read per-feature label properties: `rotation` (radians, rendered as
|
|
60
|
-
* `π − rotation`), `
|
|
61
|
-
* (ADR-
|
|
62
|
-
* `"end"` = text ends there; absent = centered).
|
|
60
|
+
* `π − rotation`), the size anchor's `textSizeMeters` (ground) or
|
|
61
|
+
* `textSizePixels` (screen) (ADR-0028), and `textAnchor` (`"start"` = text
|
|
62
|
+
* begins at the label point, `"end"` = text ends there; absent = centered).
|
|
63
|
+
* A ground-anchored label renders at
|
|
64
|
+
* `clamp(textSizeMeters / resolution, textSizeMinPixels, textSizeMaxPixels)`;
|
|
65
|
+
* a screen-anchored one at a constant `textSizePixels`, unclamped.
|
|
63
66
|
*/
|
|
64
67
|
interface TextStyleOptions {
|
|
65
68
|
text?: string;
|
|
@@ -69,6 +72,18 @@ interface TextStyleOptions {
|
|
|
69
72
|
strokeColor?: string;
|
|
70
73
|
strokeWidth?: number;
|
|
71
74
|
rotation?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Lower edge of the ground-anchored label clamp band (ADR-0028): text never
|
|
77
|
+
* renders below this pixel size, however far the view zooms out.
|
|
78
|
+
* @default 8
|
|
79
|
+
*/
|
|
80
|
+
textSizeMinPixels?: number;
|
|
81
|
+
/**
|
|
82
|
+
* Upper edge of the ground-anchored label clamp band (ADR-0028): text never
|
|
83
|
+
* renders above this pixel size, however far the view zooms in.
|
|
84
|
+
* @default 24
|
|
85
|
+
*/
|
|
86
|
+
textSizeMaxPixels?: number;
|
|
72
87
|
}
|
|
73
88
|
/**
|
|
74
89
|
* Per-feature style for edit handles (vertex / midpoint / translate / rotate).
|
|
@@ -333,6 +348,20 @@ declare function bindAbortable(signal: AbortSignal | undefined, attach: () => ()
|
|
|
333
348
|
* when missing or shaped wrong so callers fall through to the layer style.
|
|
334
349
|
*/
|
|
335
350
|
declare function coerceHandleStyle(raw: unknown): HandleStyle | undefined;
|
|
351
|
+
/** Default lower edge of the ground-anchored label clamp band (ADR-0028). */
|
|
352
|
+
declare const DEFAULT_TEXT_SIZE_MIN_PIXELS = 8;
|
|
353
|
+
/** Default upper edge of the ground-anchored label clamp band (ADR-0028). */
|
|
354
|
+
declare const DEFAULT_TEXT_SIZE_MAX_PIXELS = 24;
|
|
355
|
+
/**
|
|
356
|
+
* Rendered pixel size of a ground-anchored label (ADR-0028):
|
|
357
|
+
* `textSizeMeters / resolution`, clamped to the layer's text-style band.
|
|
358
|
+
* Within the band the text scales with its graphic; past either edge it pins
|
|
359
|
+
* to the bound, so zooming out never yields unreadable smudges and zooming in
|
|
360
|
+
* never yields screen-covering text. Shared by the adapters that resolve text
|
|
361
|
+
* size in code (OpenLayers, Leaflet); the MapLibre adapter evaluates the same
|
|
362
|
+
* clamp inside its per-zoom-stop style expression.
|
|
363
|
+
*/
|
|
364
|
+
declare function resolveGroundTextSizePixels(textSizeMeters: number, resolution: number, text?: Pick<TextStyleOptions, "textSizeMinPixels" | "textSizeMaxPixels">): number;
|
|
336
365
|
//#endregion
|
|
337
366
|
//#region src/gestures/hit-test.d.ts
|
|
338
367
|
type ToPixel = (lonLat: Position) => PixelCoordinate | null;
|
|
@@ -1167,11 +1196,12 @@ declare class TacticalDraw {
|
|
|
1167
1196
|
private renderMeasuresToGraphics;
|
|
1168
1197
|
/**
|
|
1169
1198
|
* Re-render the graphics layer on a view (zoom) change so pixel-denominated
|
|
1170
|
-
* measures rescale live. Skipped entirely
|
|
1171
|
-
*
|
|
1172
|
-
*
|
|
1173
|
-
*
|
|
1174
|
-
*
|
|
1199
|
+
* and not-yet-committed label-sized measures rescale live. Skipped entirely
|
|
1200
|
+
* when nothing rendered still reads live view state — meter geometry with a
|
|
1201
|
+
* captured label size is zoom-independent, so a rebuild would be wasted
|
|
1202
|
+
* layer writes. During an active edit the edited measure lives on the
|
|
1203
|
+
* preview layer (lifted from graphics), so it is excluded here exactly as
|
|
1204
|
+
* in `render()`; the preview's own view-change subscription rescales it.
|
|
1175
1205
|
*/
|
|
1176
1206
|
private readonly handleViewChange;
|
|
1177
1207
|
/**
|
|
@@ -1486,4 +1516,4 @@ declare function nearestWorldCopyLng(lng: number, refLng: number): number;
|
|
|
1486
1516
|
/** `nearestWorldCopyLng` applied to a lon/lat position. */
|
|
1487
1517
|
declare function nearestWorldCopyPosition(position: Position, refLng: number): Position;
|
|
1488
1518
|
//#endregion
|
|
1489
|
-
export { BaseMapAdapter, type CombinedAbort, type DrawMeasureDraft, type DrawOptions, type DrawSession, type EditChangeEvent, type EditManyOptions, type EditMode, type EditOptions, type EditPointerDriver, type EditSession, type FeatureOps, type GuideStyle, type HandleStyle, type InteractionStyle, type LayerId, type MapAdapter, type MapCursor, type MapEvent, type MapEventHandler, type NativeEventEntry, type PickEvent, type PickHandler, type PickOptions, type PixelCoordinate, type PointerCallback, PointerCallbackHub, type PointerEventInfo, type SettleReason, type SizeAnchor, type StyleOptions, TOUCH_HIT_TOLERANCE_PX, TacticalDraw, TacticalDrawAbortError, type TacticalDrawAbortReason, TacticalDrawDestroyedError, type TacticalDrawLayerOptions, type TacticalDrawOptions, type TextStyleOptions, type ToPixel, type TransformBox, type TransformChangeEvent, type TransformSession, bindAbortable, coerceHandleStyle, combineWithHostSignal, getSizeAnchor, hitTestFeature, ignoreAbort, isTacticalDrawAbortError, nearestWorldCopyLng, nearestWorldCopyPosition, pickHitTolerance, tryControlMeasureIdFromFeature };
|
|
1519
|
+
export { BaseMapAdapter, type CombinedAbort, DEFAULT_TEXT_SIZE_MAX_PIXELS, DEFAULT_TEXT_SIZE_MIN_PIXELS, type DrawMeasureDraft, type DrawOptions, type DrawSession, type EditChangeEvent, type EditManyOptions, type EditMode, type EditOptions, type EditPointerDriver, type EditSession, type FeatureOps, type GuideStyle, type HandleStyle, type InteractionStyle, type LayerId, type MapAdapter, type MapCursor, type MapEvent, type MapEventHandler, type NativeEventEntry, type PickEvent, type PickHandler, type PickOptions, type PixelCoordinate, type PointerCallback, PointerCallbackHub, type PointerEventInfo, type SettleReason, type SizeAnchor, type StyleOptions, TOUCH_HIT_TOLERANCE_PX, TacticalDraw, TacticalDrawAbortError, type TacticalDrawAbortReason, TacticalDrawDestroyedError, type TacticalDrawLayerOptions, type TacticalDrawOptions, type TextStyleOptions, type ToPixel, type TransformBox, type TransformChangeEvent, type TransformSession, bindAbortable, coerceHandleStyle, combineWithHostSignal, getSizeAnchor, hitTestFeature, ignoreAbort, isTacticalDrawAbortError, nearestWorldCopyLng, nearestWorldCopyPosition, pickHitTolerance, resolveGroundTextSizePixels, tryControlMeasureIdFromFeature };
|
package/dist/index.mjs
CHANGED
|
@@ -232,6 +232,24 @@ function coerceHandleStyle(raw) {
|
|
|
232
232
|
if (!raw || typeof raw !== "object") return void 0;
|
|
233
233
|
return raw;
|
|
234
234
|
}
|
|
235
|
+
/** Default lower edge of the ground-anchored label clamp band (ADR-0028). */
|
|
236
|
+
const DEFAULT_TEXT_SIZE_MIN_PIXELS = 8;
|
|
237
|
+
/** Default upper edge of the ground-anchored label clamp band (ADR-0028). */
|
|
238
|
+
const DEFAULT_TEXT_SIZE_MAX_PIXELS = 24;
|
|
239
|
+
/**
|
|
240
|
+
* Rendered pixel size of a ground-anchored label (ADR-0028):
|
|
241
|
+
* `textSizeMeters / resolution`, clamped to the layer's text-style band.
|
|
242
|
+
* Within the band the text scales with its graphic; past either edge it pins
|
|
243
|
+
* to the bound, so zooming out never yields unreadable smudges and zooming in
|
|
244
|
+
* never yields screen-covering text. Shared by the adapters that resolve text
|
|
245
|
+
* size in code (OpenLayers, Leaflet); the MapLibre adapter evaluates the same
|
|
246
|
+
* clamp inside its per-zoom-stop style expression.
|
|
247
|
+
*/
|
|
248
|
+
function resolveGroundTextSizePixels(textSizeMeters, resolution, text) {
|
|
249
|
+
const min = text?.textSizeMinPixels ?? 8;
|
|
250
|
+
const max = text?.textSizeMaxPixels ?? 24;
|
|
251
|
+
return Math.min(max, Math.max(min, textSizeMeters / resolution));
|
|
252
|
+
}
|
|
235
253
|
//#endregion
|
|
236
254
|
//#region src/gestures/hit-test.ts
|
|
237
255
|
/** Squared distance from `pixel` to the segment p1→p2 in pixel space, or null if either endpoint fails to project or the segment has zero length. */
|
|
@@ -504,11 +522,14 @@ function combineWithHostSignal(hostSignal) {
|
|
|
504
522
|
};
|
|
505
523
|
}
|
|
506
524
|
/**
|
|
507
|
-
* Per-kind pixel-denominated size option and the meter option it
|
|
508
|
-
* the single source of which option makes a measure
|
|
509
|
-
*
|
|
510
|
-
*
|
|
511
|
-
*
|
|
525
|
+
* Per-kind pixel-denominated *geometry* size option and the meter option it
|
|
526
|
+
* bakes into — the single source of which geometry option makes a measure
|
|
527
|
+
* screen-anchored. Label sizing is not listed here: every `capturesLabelSize`
|
|
528
|
+
* kind carries the shared `labelSizePixels` → `labelSize` pair implicitly
|
|
529
|
+
* (ADR-0028) — see [[sizeOptionSpecs]]. Both the resolution gate
|
|
530
|
+
* ([[measureUsesAdapterResolution]]) and the bake ([[bakePixelSizeToGround]])
|
|
531
|
+
* derive from this table, so a new pixel-sized kind is one entry here
|
|
532
|
+
* (ADR-0020).
|
|
512
533
|
*/
|
|
513
534
|
const PIXEL_SIZE_OPTIONS = {
|
|
514
535
|
boundary: {
|
|
@@ -523,6 +544,14 @@ const PIXEL_SIZE_OPTIONS = {
|
|
|
523
544
|
pixels: "echelonSizePixels",
|
|
524
545
|
meters: "echelonSize"
|
|
525
546
|
},
|
|
547
|
+
"base-camp": {
|
|
548
|
+
pixels: "echelonSizePixels",
|
|
549
|
+
meters: "echelonSize"
|
|
550
|
+
},
|
|
551
|
+
"guerrilla-base": {
|
|
552
|
+
pixels: "echelonSizePixels",
|
|
553
|
+
meters: "echelonSize"
|
|
554
|
+
},
|
|
526
555
|
flot: {
|
|
527
556
|
pixels: "radiusPixels",
|
|
528
557
|
meters: "radius"
|
|
@@ -548,19 +577,52 @@ const PIXEL_SIZE_OPTIONS = {
|
|
|
548
577
|
meters: "toothHeight"
|
|
549
578
|
}
|
|
550
579
|
};
|
|
580
|
+
/** The shared label-size pair every `capturesLabelSize` kind carries (ADR-0028). */
|
|
581
|
+
const LABEL_SIZE_SPEC = {
|
|
582
|
+
pixels: "labelSizePixels",
|
|
583
|
+
meters: "labelSize"
|
|
584
|
+
};
|
|
585
|
+
/**
|
|
586
|
+
* Every pixel/meter size-option pair `kind` can carry: its geometry entry from
|
|
587
|
+
* [[PIXEL_SIZE_OPTIONS]] (if any) plus the shared label pair when the kind
|
|
588
|
+
* captures a label size — a kind like Boundary can carry both anchor-bearing
|
|
589
|
+
* dimensions at once (echelon glyph + labels).
|
|
590
|
+
*/
|
|
591
|
+
function sizeOptionSpecs(kind) {
|
|
592
|
+
const specs = [];
|
|
593
|
+
const geometry = PIXEL_SIZE_OPTIONS[kind];
|
|
594
|
+
if (geometry) specs.push(geometry);
|
|
595
|
+
if (getControlMeasureMetadata(kind).capturesLabelSize) specs.push(LABEL_SIZE_SPEC);
|
|
596
|
+
return specs;
|
|
597
|
+
}
|
|
551
598
|
/**
|
|
552
599
|
* Whether `measure` carries a pixel-denominated size option whose resolution
|
|
553
600
|
* to meters depends on the live map (`metersPerPixel`) — i.e. it is
|
|
554
601
|
* *screen-anchored*. Used both to inject the override
|
|
555
602
|
* ([[withAdapterMeasureOptions]]) and to let zoom-driven re-renders skip
|
|
556
|
-
* measures whose
|
|
603
|
+
* measures whose render is resolution-independent. Accepts the minimal
|
|
557
604
|
* `{ kind, options }` shape so in-flight draw/edit handlers can gate against
|
|
558
605
|
* working options without materialising a full measure.
|
|
559
606
|
*/
|
|
560
607
|
function measureUsesAdapterResolution(measure) {
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
|
|
608
|
+
const options = measure.options;
|
|
609
|
+
return sizeOptionSpecs(measure.kind).some((spec) => options?.[spec.pixels] !== void 0);
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Whether rendering `measure` through [[renderMeasureForAdapter]] reads live
|
|
613
|
+
* adapter view state — either a pixel-denominated size
|
|
614
|
+
* ([[measureUsesAdapterResolution]]) or draw-time label sizing that
|
|
615
|
+
* [[withCommittedAdapterMeasureOptions]] would still stamp (a
|
|
616
|
+
* `capturesLabelSize` kind not yet carrying any label size). The view-change
|
|
617
|
+
* rerender gates key off this so such measures rescale live; committed
|
|
618
|
+
* ground-anchored measures carry `labelSize` meters, stay zoom-independent,
|
|
619
|
+
* and keep skipping the rebuild.
|
|
620
|
+
*/
|
|
621
|
+
function measureRendersFromViewState(measure) {
|
|
622
|
+
if (measureUsesAdapterResolution(measure)) return true;
|
|
623
|
+
if (!getControlMeasureMetadata(measure.kind).capturesLabelSize) return false;
|
|
624
|
+
const options = measure.options;
|
|
625
|
+
return typeof options?.labelSizePixels !== "number" && typeof options?.labelSize !== "number";
|
|
564
626
|
}
|
|
565
627
|
/**
|
|
566
628
|
* The [[SizeAnchor]] a measure currently encodes (ADR-0020): `screen` when it
|
|
@@ -582,16 +644,15 @@ function getSizeAnchor(measure) {
|
|
|
582
644
|
* carries no pixel size or the adapter has no usable resolution.
|
|
583
645
|
*/
|
|
584
646
|
function bakePixelSizeToGround(measure, adapter) {
|
|
585
|
-
const spec = PIXEL_SIZE_OPTIONS[measure.kind];
|
|
586
|
-
if (!spec) return measure;
|
|
587
647
|
const options = measure.options ?? {};
|
|
588
|
-
const
|
|
589
|
-
if (
|
|
648
|
+
const specs = sizeOptionSpecs(measure.kind).filter((spec) => typeof options[spec.pixels] === "number");
|
|
649
|
+
if (specs.length === 0) return measure;
|
|
590
650
|
const mpp = adapter.getResolution();
|
|
591
651
|
if (mpp === void 0 || mpp <= 0) return measure;
|
|
652
|
+
const pixelKeys = new Set(specs.map((spec) => spec.pixels));
|
|
592
653
|
const rest = {};
|
|
593
|
-
for (const [key, value] of Object.entries(options)) if (key
|
|
594
|
-
rest[spec.meters] = pixels * mpp;
|
|
654
|
+
for (const [key, value] of Object.entries(options)) if (!pixelKeys.has(key) && key !== "metersPerPixel") rest[key] = value;
|
|
655
|
+
for (const spec of specs) rest[spec.meters] = options[spec.pixels] * mpp;
|
|
595
656
|
return {
|
|
596
657
|
...measure,
|
|
597
658
|
options: rest
|
|
@@ -617,22 +678,24 @@ function withAdapterMeasureOptions(measure, adapter) {
|
|
|
617
678
|
};
|
|
618
679
|
}
|
|
619
680
|
/**
|
|
620
|
-
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
681
|
+
* Stamp the draw-time default label size, in its screen-anchored
|
|
682
|
+
* (`labelSizePixels`) form, onto a `capturesLabelSize` measure that carries no
|
|
683
|
+
* label size of its own (ADR-0028). The pixel form keeps the in-flight
|
|
684
|
+
* preview screen-anchored through the gesture; the commit's default `ground`
|
|
685
|
+
* anchor then bakes it to `labelSize` meters via [[bakePixelSizeToGround]],
|
|
686
|
+
* while a `screen` commit persists the pixels. No-op once either label-size
|
|
687
|
+
* option is present (e.g. already committed), so it's safe to call on every
|
|
688
|
+
* render as well as on commit itself — see [[renderMeasureForAdapter]].
|
|
623
689
|
*/
|
|
624
|
-
function withCommittedAdapterMeasureOptions(measure
|
|
690
|
+
function withCommittedAdapterMeasureOptions(measure) {
|
|
625
691
|
if (!getControlMeasureMetadata(measure.kind).capturesLabelSize) return measure;
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
const resolution = adapter.getResolution();
|
|
692
|
+
const options = measure.options;
|
|
693
|
+
if (typeof options?.labelSizePixels === "number" || typeof options?.labelSize === "number") return measure;
|
|
629
694
|
return {
|
|
630
695
|
...measure,
|
|
631
696
|
options: {
|
|
632
697
|
...measure.options,
|
|
633
|
-
labelSizePixels: 14
|
|
634
|
-
...zoom !== void 0 ? { labelSizeZoom: zoom } : {},
|
|
635
|
-
...resolution !== void 0 && resolution > 0 ? { labelSizeResolution: resolution } : {}
|
|
698
|
+
labelSizePixels: 14
|
|
636
699
|
}
|
|
637
700
|
};
|
|
638
701
|
}
|
|
@@ -641,10 +704,17 @@ function withCommittedAdapterMeasureOptions(measure, adapter) {
|
|
|
641
704
|
* "turn a measure into features against the live map" — every TacticalDraw
|
|
642
705
|
* layer write (graphics reconcile, draw preview, edit preview, commit snapshot)
|
|
643
706
|
* routes through here so pixel sizing is resolved identically everywhere and no
|
|
644
|
-
* call site can forget the injection.
|
|
707
|
+
* call site can forget the injection. Composes [[withAdapterMeasureOptions]]
|
|
708
|
+
* (pixel size → `metersPerPixel`) with [[withCommittedAdapterMeasureOptions]]
|
|
709
|
+
* (label size defaults for `capturesLabelSize` kinds), so draw/edit previews
|
|
710
|
+
* get the same label clearance a commit would bake in — the input `measure`
|
|
711
|
+
* is never mutated, and callers that need the persisted/working measure to
|
|
712
|
+
* stay free of these render-only options must keep using that separately
|
|
713
|
+
* (draw/edit commit paths call [[withCommittedAdapterMeasureOptions]]
|
|
714
|
+
* directly to produce the value they persist).
|
|
645
715
|
*/
|
|
646
716
|
function renderMeasureForAdapter(adapter, measure, opts) {
|
|
647
|
-
return renderControlMeasure(withAdapterMeasureOptions(measure, adapter), opts);
|
|
717
|
+
return renderControlMeasure(withAdapterMeasureOptions(withCommittedAdapterMeasureOptions(measure), adapter), opts);
|
|
648
718
|
}
|
|
649
719
|
//#endregion
|
|
650
720
|
//#region src/tactical-draw/run-interaction.ts
|
|
@@ -923,7 +993,7 @@ function runFixedLengthDraw(options) {
|
|
|
923
993
|
ctx.writeLayer(guideLayer, guideFeatures);
|
|
924
994
|
}
|
|
925
995
|
function rescaleOnViewChange() {
|
|
926
|
-
if (!
|
|
996
|
+
if (!measureRendersFromViewState({
|
|
927
997
|
kind,
|
|
928
998
|
options: measureOptions
|
|
929
999
|
})) return;
|
|
@@ -939,7 +1009,7 @@ function runFixedLengthDraw(options) {
|
|
|
939
1009
|
...measureStyle !== void 0 ? { style: measureStyle } : {},
|
|
940
1010
|
...measureProperties !== void 0 ? { properties: measureProperties } : {},
|
|
941
1011
|
...measureTextAmplifiers !== void 0 ? { textAmplifiers: measureTextAmplifiers } : {}
|
|
942
|
-
}
|
|
1012
|
+
});
|
|
943
1013
|
const measure = sizeAnchor === "screen" ? captured : bakePixelSizeToGround(captured, adapter);
|
|
944
1014
|
return {
|
|
945
1015
|
measure: cloneControlMeasure(measure),
|
|
@@ -1296,7 +1366,7 @@ function runVariableLengthDraw(options) {
|
|
|
1296
1366
|
ctx.writeLayer(guideLayer, guideFeatures);
|
|
1297
1367
|
}
|
|
1298
1368
|
function rescaleOnViewChange() {
|
|
1299
|
-
if (!
|
|
1369
|
+
if (!measureRendersFromViewState({
|
|
1300
1370
|
kind,
|
|
1301
1371
|
options: measureOptions
|
|
1302
1372
|
})) return;
|
|
@@ -1311,7 +1381,7 @@ function runVariableLengthDraw(options) {
|
|
|
1311
1381
|
...measureStyle !== void 0 ? { style: measureStyle } : {},
|
|
1312
1382
|
...measureProperties !== void 0 ? { properties: measureProperties } : {},
|
|
1313
1383
|
...measureTextAmplifiers !== void 0 ? { textAmplifiers: measureTextAmplifiers } : {}
|
|
1314
|
-
}
|
|
1384
|
+
});
|
|
1315
1385
|
const measure = sizeAnchor === "screen" ? built : bakePixelSizeToGround(built, adapter);
|
|
1316
1386
|
return {
|
|
1317
1387
|
measure: cloneControlMeasure(measure),
|
|
@@ -2107,7 +2177,7 @@ function runEdit(opts) {
|
|
|
2107
2177
|
}
|
|
2108
2178
|
function rescaleOnViewChange() {
|
|
2109
2179
|
if (ctx.settled) return;
|
|
2110
|
-
if (
|
|
2180
|
+
if (measureRendersFromViewState({
|
|
2111
2181
|
kind: measure.kind,
|
|
2112
2182
|
options: workingOptions
|
|
2113
2183
|
})) renderPreview();
|
|
@@ -3022,7 +3092,7 @@ function runGroupTransform(opts) {
|
|
|
3022
3092
|
}
|
|
3023
3093
|
function rescaleOnViewChange() {
|
|
3024
3094
|
if (ctx.settled) return;
|
|
3025
|
-
if (members.some((m) =>
|
|
3095
|
+
if (members.some((m) => measureRendersFromViewState({
|
|
3026
3096
|
kind: m.measure.kind,
|
|
3027
3097
|
options: m.measure.options
|
|
3028
3098
|
}))) renderAllPreviews();
|
|
@@ -3594,17 +3664,18 @@ var TacticalDraw = class {
|
|
|
3594
3664
|
}
|
|
3595
3665
|
/**
|
|
3596
3666
|
* Re-render the graphics layer on a view (zoom) change so pixel-denominated
|
|
3597
|
-
* measures rescale live. Skipped entirely
|
|
3598
|
-
*
|
|
3599
|
-
*
|
|
3600
|
-
*
|
|
3601
|
-
*
|
|
3667
|
+
* and not-yet-committed label-sized measures rescale live. Skipped entirely
|
|
3668
|
+
* when nothing rendered still reads live view state — meter geometry with a
|
|
3669
|
+
* captured label size is zoom-independent, so a rebuild would be wasted
|
|
3670
|
+
* layer writes. During an active edit the edited measure lives on the
|
|
3671
|
+
* preview layer (lifted from graphics), so it is excluded here exactly as
|
|
3672
|
+
* in `render()`; the preview's own view-change subscription rescales it.
|
|
3602
3673
|
*/
|
|
3603
3674
|
handleViewChange = () => {
|
|
3604
3675
|
if (this.destroyed || !this.hasRendered) return;
|
|
3605
3676
|
const excluded = this.excludedInteractionIds();
|
|
3606
3677
|
const visible = excluded.size > 0 ? this.lastRenderedMeasures.filter((m) => !excluded.has(m.id)) : this.lastRenderedMeasures;
|
|
3607
|
-
if (!visible.some(
|
|
3678
|
+
if (!visible.some(measureRendersFromViewState)) return;
|
|
3608
3679
|
this.renderMeasuresToGraphics(visible);
|
|
3609
3680
|
};
|
|
3610
3681
|
/**
|
|
@@ -4311,4 +4382,4 @@ function nearestWorldCopyPosition(position, refLng) {
|
|
|
4311
4382
|
return [nearestWorldCopyLng(position[0], refLng), ...position.slice(1)];
|
|
4312
4383
|
}
|
|
4313
4384
|
//#endregion
|
|
4314
|
-
export { BaseMapAdapter, PointerCallbackHub, TOUCH_HIT_TOLERANCE_PX, TacticalDraw, TacticalDrawAbortError, TacticalDrawDestroyedError, bindAbortable, coerceHandleStyle, combineWithHostSignal, getSizeAnchor, hitTestFeature, ignoreAbort, isTacticalDrawAbortError, nearestWorldCopyLng, nearestWorldCopyPosition, pickHitTolerance, tryControlMeasureIdFromFeature };
|
|
4385
|
+
export { BaseMapAdapter, DEFAULT_TEXT_SIZE_MAX_PIXELS, DEFAULT_TEXT_SIZE_MIN_PIXELS, PointerCallbackHub, TOUCH_HIT_TOLERANCE_PX, TacticalDraw, TacticalDrawAbortError, TacticalDrawDestroyedError, bindAbortable, coerceHandleStyle, combineWithHostSignal, getSizeAnchor, hitTestFeature, ignoreAbort, isTacticalDrawAbortError, nearestWorldCopyLng, nearestWorldCopyPosition, pickHitTolerance, resolveGroundTextSizePixels, tryControlMeasureIdFromFeature };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orbat-mapper/tactical-draw",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.14",
|
|
4
4
|
"description": "Engine-agnostic draw/edit core for tactical control measures (MIL-STD-2525 / APP-6). The MapAdapter ABI and bring-your-own-engine entry point for the tactical-draw package family.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Orbat Mapper",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@orbat-mapper/control-measures": "^0.2.0-alpha.
|
|
41
|
+
"@orbat-mapper/control-measures": "^0.2.0-alpha.11"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@arethetypeswrong/core": "^0.18.3",
|