bruce-cesium 7.4.0 → 7.4.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/bruce-cesium.es5.js +248 -85
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +246 -83
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +1 -1
- package/dist/lib/rendering/render-managers/common/entity-label-group.js +60 -4
- package/dist/lib/rendering/render-managers/common/entity-label-group.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/entity-label.js +185 -78
- package/dist/lib/rendering/render-managers/common/entity-label.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +1 -1
- package/dist/types/rendering/render-managers/common/entity-label-group.d.ts +6 -1
- package/dist/types/rendering/render-managers/common/entity-label.d.ts +4 -1
- package/package.json +1 -1
package/dist/bruce-cesium.umd.js
CHANGED
|
@@ -5383,7 +5383,14 @@
|
|
|
5383
5383
|
(function (EntityLabel) {
|
|
5384
5384
|
const ICON_BACKGROUND_BLEND = 0.8;
|
|
5385
5385
|
const ICON_BACKGROUND_ALPHA = 0.45;
|
|
5386
|
+
// Under this much difference between the glyph's width and height the chip is squared off,
|
|
5387
|
+
// so a row of labels reads as one size rather than a set of differently shaped pills.
|
|
5388
|
+
const ICON_BACKGROUND_UNIFORM_TOLERANCE = 0.3;
|
|
5386
5389
|
const TEXT_MAX_WIDTH = 200;
|
|
5390
|
+
// How far an angled leader runs sideways before the label starts.
|
|
5391
|
+
const ANGLED_LEADER_RUN = 28;
|
|
5392
|
+
// One per tinted icon, since an SVG mask is addressed by id across the whole document.
|
|
5393
|
+
let tintCounter = 0;
|
|
5387
5394
|
// Key where the label instance is stored within the cesium entity.
|
|
5388
5395
|
// Eg: rego[ATTACH_KEY] = new EntityLabel(...);
|
|
5389
5396
|
EntityLabel.ATTACH_KEY = "nextspace-navigator-entity-label";
|
|
@@ -5482,7 +5489,7 @@
|
|
|
5482
5489
|
this.nextOrder = 0;
|
|
5483
5490
|
}
|
|
5484
5491
|
Resolve(frames) {
|
|
5485
|
-
var _a, _b;
|
|
5492
|
+
var _a, _b, _c;
|
|
5486
5493
|
const live = new Set(frames.map(frame => frame.id));
|
|
5487
5494
|
const moved = (frame) => {
|
|
5488
5495
|
var _a;
|
|
@@ -5509,10 +5516,17 @@
|
|
|
5509
5516
|
const placed = new Map();
|
|
5510
5517
|
const next = new Map();
|
|
5511
5518
|
const candidate = (frame, side) => {
|
|
5512
|
-
var _a;
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5519
|
+
var _a, _b;
|
|
5520
|
+
if (!frame.canFlip) {
|
|
5521
|
+
return frame;
|
|
5522
|
+
}
|
|
5523
|
+
if (frame.leaderRun != null) {
|
|
5524
|
+
const x = side === "left" ? frame.anchorX - frame.leaderRun - frame.width : frame.anchorX + frame.leaderRun;
|
|
5525
|
+
return { ...frame, x: Math.max(0, Math.min(x, ((_a = frame.viewportWidth) !== null && _a !== void 0 ? _a : Infinity) - frame.width)) };
|
|
5526
|
+
}
|
|
5527
|
+
return (side === "left" ?
|
|
5528
|
+
{ ...frame, x: Math.max(0, Math.min(frame.anchorX - frame.width, ((_b = frame.viewportWidth) !== null && _b !== void 0 ? _b : Infinity) - frame.width)) }
|
|
5529
|
+
: frame);
|
|
5516
5530
|
};
|
|
5517
5531
|
const score = (frame, padding = 0) => {
|
|
5518
5532
|
const box = {
|
|
@@ -5528,7 +5542,7 @@
|
|
|
5528
5542
|
};
|
|
5529
5543
|
for (const frame of ordered) {
|
|
5530
5544
|
const old = this.previous.get(frame.id);
|
|
5531
|
-
let side = frame.canFlip ? (_a = old === null || old === void 0 ? void 0 : old.side) !== null && _a !== void 0 ? _a : "right" : "right";
|
|
5545
|
+
let side = frame.canFlip ? (_b = (_a = old === null || old === void 0 ? void 0 : old.side) !== null && _a !== void 0 ? _a : frame.leaderSide) !== null && _b !== void 0 ? _b : "right" : "right";
|
|
5532
5546
|
let chosen = candidate(frame, side);
|
|
5533
5547
|
if (!fixed(frame) && frame.canFlip) {
|
|
5534
5548
|
const otherSide = side === "left" ? "right" : "left";
|
|
@@ -5540,7 +5554,7 @@
|
|
|
5540
5554
|
}
|
|
5541
5555
|
}
|
|
5542
5556
|
placed.set(frame.id, { frame: chosen, side });
|
|
5543
|
-
next.set(frame.id, { frame: fixed(frame) ? old.frame : { ...frame }, side, order: (
|
|
5557
|
+
next.set(frame.id, { frame: fixed(frame) ? old.frame : { ...frame }, side, order: (_c = old === null || old === void 0 ? void 0 : old.order) !== null && _c !== void 0 ? _c : this.nextOrder++ });
|
|
5544
5558
|
text.Add(chosen);
|
|
5545
5559
|
const stem = leaderBounds(chosen);
|
|
5546
5560
|
if (stem) {
|
|
@@ -5560,7 +5574,7 @@
|
|
|
5560
5574
|
* Resolves clustering and stable text placement before depth fading; highlighted labels receive priority.
|
|
5561
5575
|
*/
|
|
5562
5576
|
function Layout(input, memory = new PlacementMemory()) {
|
|
5563
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
5577
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
5564
5578
|
const frames = input.filter(frame => [frame.x, frame.y, frame.width, frame.height, frame.depth].every(Number.isFinite))
|
|
5565
5579
|
.sort((a, b) => (b.priority || 0) - (a.priority || 0) || a.depth - b.depth || a.id.localeCompare(b.id));
|
|
5566
5580
|
const result = new Map();
|
|
@@ -5626,17 +5640,13 @@
|
|
|
5626
5640
|
}
|
|
5627
5641
|
}
|
|
5628
5642
|
if (values.size > 1) {
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
if (values.size > 2)
|
|
5637
|
-
rows.push(`+${values.size - 2} more…`);
|
|
5638
|
-
representative.text = rows.join("\n");
|
|
5639
|
-
}
|
|
5643
|
+
// A value long enough to wrap fills the box on its own, so only one is listed.
|
|
5644
|
+
const wrapped = stableMembers.some(member => { var _a, _b; return member.textWrapped && ((_b = (member.text || ((_a = member.options) === null || _a === void 0 ? void 0 : _a.text))) === null || _b === void 0 ? void 0 : _b.trim()); });
|
|
5645
|
+
const limit = wrapped ? 1 : 2;
|
|
5646
|
+
const rows = Array.from(values).slice(0, limit);
|
|
5647
|
+
if (values.size > limit)
|
|
5648
|
+
rows.push(`+${values.size - limit} more…`);
|
|
5649
|
+
representative.text = rows.join("\n");
|
|
5640
5650
|
}
|
|
5641
5651
|
}
|
|
5642
5652
|
for (const frame of cluster.members) {
|
|
@@ -5660,7 +5670,7 @@
|
|
|
5660
5670
|
const box = { ...frame, x: frame.x + .01, y: frame.y + .01, width: Math.max(0, frame.width - .02), height: Math.max(0, frame.height - .02) };
|
|
5661
5671
|
const overlap = foreground.HasOverlap(box) || foregroundLeaders.HasOverlap(box) || Boolean(stem && foreground.HasOverlap(stem));
|
|
5662
5672
|
if (overlap) {
|
|
5663
|
-
placement.opacity *= Math.max(0, Math.min(1, (
|
|
5673
|
+
placement.opacity *= Math.max(0, Math.min(1, (_g = (_f = frame.options) === null || _f === void 0 ? void 0 : _f.overlapOpacity) !== null && _g !== void 0 ? _g : 0.25));
|
|
5664
5674
|
}
|
|
5665
5675
|
placement.zIndex = zIndex--;
|
|
5666
5676
|
foreground.Add(frame);
|
|
@@ -5982,6 +5992,8 @@
|
|
|
5982
5992
|
this.loadTimeout = null;
|
|
5983
5993
|
this.loadedName = false;
|
|
5984
5994
|
this.line = null;
|
|
5995
|
+
// The sideways half of an angled leader; the rise is drawn by line.
|
|
5996
|
+
this.leaderRun = null;
|
|
5985
5997
|
this.anchor = null;
|
|
5986
5998
|
// Null = not attempted to load.
|
|
5987
5999
|
this.additionalTexts = null;
|
|
@@ -6378,6 +6390,7 @@
|
|
|
6378
6390
|
}
|
|
6379
6391
|
};
|
|
6380
6392
|
const normalLeader = (_k = this.options.leader) !== null && _k !== void 0 ? _k : presentation === "text";
|
|
6393
|
+
const angled = this.options.leaderStyle === "angled";
|
|
6381
6394
|
let leader = normalLeader;
|
|
6382
6395
|
const content = document.createElement("span");
|
|
6383
6396
|
const originalText = (_l = this.options.text) !== null && _l !== void 0 ? _l : [text, ...additionalTexts].join("\n");
|
|
@@ -6386,6 +6399,7 @@
|
|
|
6386
6399
|
let sourceNaturalText;
|
|
6387
6400
|
let iconElement;
|
|
6388
6401
|
let iconContainer;
|
|
6402
|
+
let fitIconBackground;
|
|
6389
6403
|
content.className = "entity-label-content";
|
|
6390
6404
|
content.style.cssText = "display:flex;align-items:center;gap:6px;";
|
|
6391
6405
|
if (presentation === "icon-text-above") {
|
|
@@ -6408,34 +6422,49 @@
|
|
|
6408
6422
|
image.alt = this.options.icon || "";
|
|
6409
6423
|
const scale = (_o = this.options.iconScale) !== null && _o !== void 0 ? _o : 1;
|
|
6410
6424
|
const size = this.options.iconSize;
|
|
6411
|
-
const
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
mask
|
|
6418
|
-
mask.
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
}
|
|
6425
|
+
const svgNs = "http://www.w3.org/2000/svg";
|
|
6426
|
+
const tint = iconColor ? document.createElementNS(svgNs, "svg") : null;
|
|
6427
|
+
const painted = tint ? document.createElementNS(svgNs, "image") : null;
|
|
6428
|
+
const inked = tint ? document.createElementNS(svgNs, "rect") : null;
|
|
6429
|
+
if (tint) {
|
|
6430
|
+
const maskId = `entity-label-tint-${++tintCounter}`;
|
|
6431
|
+
const mask = document.createElementNS(svgNs, "mask");
|
|
6432
|
+
mask.setAttribute("id", maskId);
|
|
6433
|
+
mask.setAttribute("maskUnits", "userSpaceOnUse");
|
|
6434
|
+
painted.setAttribute("href", this.options.iconUrl);
|
|
6435
|
+
painted.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
|
6436
|
+
mask.appendChild(painted);
|
|
6437
|
+
inked.setAttribute("fill", iconColor);
|
|
6438
|
+
inked.setAttribute("mask", `url(#${maskId})`);
|
|
6439
|
+
tint.append(mask, inked);
|
|
6440
|
+
tint.style.display = "block";
|
|
6441
|
+
icon.style.display = "inline-flex";
|
|
6442
|
+
icon.appendChild(tint);
|
|
6425
6443
|
}
|
|
6426
6444
|
const resize = () => {
|
|
6427
6445
|
if (this.disposed || this.counter !== counter) {
|
|
6428
6446
|
return;
|
|
6429
6447
|
}
|
|
6430
6448
|
const intrinsic = this.options.iconScale != null && size == null;
|
|
6431
|
-
|
|
6432
|
-
|
|
6449
|
+
const width = (intrinsic ? image.naturalWidth || 24 : size || 24) * scale;
|
|
6450
|
+
const height = (intrinsic ? image.naturalHeight || 24 : size || 24) * scale;
|
|
6451
|
+
if (tint) {
|
|
6452
|
+
tint.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
6453
|
+
for (const node of [tint, painted, inked]) {
|
|
6454
|
+
node.setAttribute("width", String(width));
|
|
6455
|
+
node.setAttribute("height", String(height));
|
|
6456
|
+
}
|
|
6457
|
+
}
|
|
6458
|
+
else {
|
|
6459
|
+
image.style.width = `${width}px`;
|
|
6460
|
+
image.style.height = `${height}px`;
|
|
6461
|
+
}
|
|
6433
6462
|
this.viewer.scene.requestRender();
|
|
6434
6463
|
};
|
|
6435
6464
|
image.onload = resize;
|
|
6436
6465
|
resize();
|
|
6437
6466
|
image.src = this.options.iconUrl;
|
|
6438
|
-
if (!
|
|
6467
|
+
if (!tint) {
|
|
6439
6468
|
icon.appendChild(image);
|
|
6440
6469
|
}
|
|
6441
6470
|
}
|
|
@@ -6460,6 +6489,27 @@
|
|
|
6460
6489
|
icon.style.minWidth = `${size}px`;
|
|
6461
6490
|
icon.style.minHeight = `${size}px`;
|
|
6462
6491
|
icon.style.boxSizing = "content-box";
|
|
6492
|
+
let fitted = false;
|
|
6493
|
+
fitIconBackground = () => {
|
|
6494
|
+
if (fitted) {
|
|
6495
|
+
return;
|
|
6496
|
+
}
|
|
6497
|
+
const padding = size / 3;
|
|
6498
|
+
const width = icon.offsetWidth - padding * 2;
|
|
6499
|
+
const height = icon.offsetHeight - padding * 2;
|
|
6500
|
+
if (width <= 0 || height <= 0) {
|
|
6501
|
+
return;
|
|
6502
|
+
}
|
|
6503
|
+
fitted = true;
|
|
6504
|
+
const longest = Math.max(width, height);
|
|
6505
|
+
const difference = (longest - Math.min(width, height)) / longest;
|
|
6506
|
+
if (difference > ICON_BACKGROUND_UNIFORM_TOLERANCE) {
|
|
6507
|
+
return;
|
|
6508
|
+
}
|
|
6509
|
+
icon.style.minWidth = `${longest}px`;
|
|
6510
|
+
icon.style.minHeight = `${longest}px`;
|
|
6511
|
+
this.viewer.scene.requestRender();
|
|
6512
|
+
};
|
|
6463
6513
|
}
|
|
6464
6514
|
if (this.options.iconScale === 0) {
|
|
6465
6515
|
icon.style.display = "none";
|
|
@@ -6498,8 +6548,10 @@
|
|
|
6498
6548
|
const countElement = document.createElement("span");
|
|
6499
6549
|
countElement.className = "entity-label-count";
|
|
6500
6550
|
countElement.style.cssText = "flex:none;align-self:center;white-space:nowrap;background:#fff;color:#000;text-shadow:none;border-radius:8px;padding:0 3px;display:none;";
|
|
6551
|
+
// Text above the icon would have the badge land in it, so the free corner is the lower one.
|
|
6552
|
+
const badgeBelow = presentation === "icon-text-above";
|
|
6501
6553
|
if (iconContainer) {
|
|
6502
|
-
countElement.style.cssText +=
|
|
6554
|
+
countElement.style.cssText += `position:absolute;left:100%;top:${badgeBelow ? "100%" : "0"};transform:translate(-50%,-50%);`;
|
|
6503
6555
|
iconContainer.appendChild(countElement);
|
|
6504
6556
|
}
|
|
6505
6557
|
if (!layers.has(this.viewer)) {
|
|
@@ -6508,6 +6560,7 @@
|
|
|
6508
6560
|
const layer = layers.get(this.viewer);
|
|
6509
6561
|
let ele = null;
|
|
6510
6562
|
let lineEle = null;
|
|
6563
|
+
let runEle = null;
|
|
6511
6564
|
if (this.label) {
|
|
6512
6565
|
ele = this.label;
|
|
6513
6566
|
}
|
|
@@ -6544,6 +6597,7 @@
|
|
|
6544
6597
|
}
|
|
6545
6598
|
if (this.line) {
|
|
6546
6599
|
lineEle = this.line;
|
|
6600
|
+
runEle = this.leaderRun;
|
|
6547
6601
|
}
|
|
6548
6602
|
else {
|
|
6549
6603
|
lineEle = document.createElement("div");
|
|
@@ -6587,6 +6641,14 @@
|
|
|
6587
6641
|
layer.element.appendChild(lineEleNode);
|
|
6588
6642
|
layer.element.appendChild(lineEle);
|
|
6589
6643
|
}
|
|
6644
|
+
// Built here rather than beside the stem, since the style can change on a label that is reused.
|
|
6645
|
+
if (angled && !runEle) {
|
|
6646
|
+
runEle = lineEle.cloneNode(false);
|
|
6647
|
+
runEle.className = "entity-label-leader-run";
|
|
6648
|
+
runEle.style.display = "none";
|
|
6649
|
+
this.leaderRun = runEle;
|
|
6650
|
+
layer.element.appendChild(runEle);
|
|
6651
|
+
}
|
|
6590
6652
|
let MAX_DISTANCE = Math.max(15000, sizeInM * 35);
|
|
6591
6653
|
if (visual && visual instanceof Cesium.Entity) {
|
|
6592
6654
|
// Consistent sized things.
|
|
@@ -6606,6 +6668,25 @@
|
|
|
6606
6668
|
y: upwards ? endY - height : endY, endY
|
|
6607
6669
|
};
|
|
6608
6670
|
};
|
|
6671
|
+
/*
|
|
6672
|
+
* An angled leader parks the label beside the anchor instead of over it,
|
|
6673
|
+
* so the stem rises to the label's middle and then runs out to whichever side has the room.
|
|
6674
|
+
*/
|
|
6675
|
+
const fitAngledLeader = (anchorX, anchorY, desired, width, height, radius = 0) => {
|
|
6676
|
+
const canvas = this.viewer.canvas;
|
|
6677
|
+
const above = Math.max(0, anchorY - height / 2);
|
|
6678
|
+
const below = Math.max(0, canvas.clientHeight - anchorY - height / 2);
|
|
6679
|
+
const upwards = above >= Math.max(radius ? radius + 4 : 0, Math.min(8, desired)) || above >= below;
|
|
6680
|
+
const length = Math.min(desired, upwards ? above : below);
|
|
6681
|
+
const endY = anchorY + (upwards ? -length : length);
|
|
6682
|
+
const run = Math.max(ANGLED_LEADER_RUN, radius + 4);
|
|
6683
|
+
const rightwards = anchorX + run + width <= canvas.clientWidth || anchorX - run - width < 0;
|
|
6684
|
+
return {
|
|
6685
|
+
x: Math.max(0, Math.min(rightwards ? anchorX + run : anchorX - run - width, canvas.clientWidth - width)),
|
|
6686
|
+
y: Math.max(0, Math.min(endY - height / 2, canvas.clientHeight - height)), endY,
|
|
6687
|
+
run, side: (rightwards ? "right" : "left")
|
|
6688
|
+
};
|
|
6689
|
+
};
|
|
6609
6690
|
let cursorMotion = this.cursorMotion;
|
|
6610
6691
|
const project = () => {
|
|
6611
6692
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
@@ -6743,7 +6824,14 @@
|
|
|
6743
6824
|
y -= height / 2;
|
|
6744
6825
|
}
|
|
6745
6826
|
// Membership uses the unclamped source footprint, never the summary's changing dimensions.
|
|
6746
|
-
|
|
6827
|
+
let leaderRun;
|
|
6828
|
+
let leaderSide;
|
|
6829
|
+
if (leader && angled) {
|
|
6830
|
+
const fit = fitAngledLeader(anchorX, anchorY, leaderLength, width, height);
|
|
6831
|
+
({ x, y } = fit);
|
|
6832
|
+
({ run: leaderRun, side: leaderSide } = fit);
|
|
6833
|
+
}
|
|
6834
|
+
else if (leader)
|
|
6747
6835
|
({ x, y } = fitLeader(anchorX, anchorY, leaderLength, width, height));
|
|
6748
6836
|
const bounds = clusterBounds || { x, y, width, height };
|
|
6749
6837
|
if (!leader && (bounds.x + bounds.width < 0 || bounds.y + bounds.height < 0 || bounds.x > this.viewer.canvas.clientWidth || bounds.y > this.viewer.canvas.clientHeight)) {
|
|
@@ -6758,20 +6846,21 @@
|
|
|
6758
6846
|
extendedGeometry: visual instanceof Cesium.Entity && Boolean(visual.polygon || visual.polyline || visual.corridor),
|
|
6759
6847
|
viewportWidth: this.viewer.canvas.clientWidth,
|
|
6760
6848
|
id: this.id, entityKey: ((_s = this.rego) === null || _s === void 0 ? void 0 : _s.entityId) ? JSON.stringify([this.rego.entityId, this.rego.menuItemId || "", this.Transient && !this.Persistent ? "hover" : ""]) : undefined,
|
|
6761
|
-
entityId: (_t = this.rego) === null || _t === void 0 ? void 0 : _t.entityId, group: this.groupId, x, y, width, height, anchorX, anchorY, depth, leaderLength, distance,
|
|
6849
|
+
entityId: (_t = this.rego) === null || _t === void 0 ? void 0 : _t.entityId, group: this.groupId, x, y, width, height, anchorX, anchorY, depth, leaderLength, leaderRun, leaderSide, distance,
|
|
6762
6850
|
// Priority shows the hovered member individually without dragging its cluster along.
|
|
6763
6851
|
opacity, priority: hover || cursorAmount > 0 || (state === null || state === void 0 ? void 0 : state.highlighted) ? 1 : 0, options: this.options, text: originalText, clusterBounds
|
|
6764
6852
|
};
|
|
6765
6853
|
};
|
|
6766
6854
|
let displacement = { x: 0, y: 0 };
|
|
6767
|
-
let displayedSummaryMore = false;
|
|
6768
6855
|
let nudge = { x: 0, y: 0, fromX: 0, fromY: 0, targetX: 0, targetY: 0, start: 0 };
|
|
6769
6856
|
const apply = (placement) => {
|
|
6770
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
|
|
6857
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
|
|
6771
6858
|
const show = (placement === null || placement === void 0 ? void 0 : placement.visible) && placement.opacity > 0;
|
|
6772
6859
|
clickEntityIds = show ? placement.entityIds : [];
|
|
6773
6860
|
ele.style.visibility = show ? "visible" : "hidden";
|
|
6774
6861
|
lineEle.style.display = show && leader ? "block" : "none";
|
|
6862
|
+
if (runEle)
|
|
6863
|
+
runEle.style.display = show && leader ? "block" : "none";
|
|
6775
6864
|
this.anchor.style.display = show && leader ? "block" : "none";
|
|
6776
6865
|
if (!show) {
|
|
6777
6866
|
displacement = { x: 0, y: 0 };
|
|
@@ -6782,17 +6871,8 @@
|
|
|
6782
6871
|
return;
|
|
6783
6872
|
}
|
|
6784
6873
|
const displayText = (_a = placement.text) !== null && _a !== void 0 ? _a : originalText;
|
|
6785
|
-
|
|
6786
|
-
if (textElement && (textElement.textContent !== displayText + (summaryMore ? "\n…" : "") || displayedSummaryMore !== summaryMore)) {
|
|
6874
|
+
if (textElement && textElement.textContent !== displayText) {
|
|
6787
6875
|
textElement.textContent = displayText;
|
|
6788
|
-
if (summaryMore) {
|
|
6789
|
-
const more = document.createElement("span");
|
|
6790
|
-
more.className = "entity-label-more";
|
|
6791
|
-
more.style.opacity = "0.65";
|
|
6792
|
-
more.textContent = "\n…";
|
|
6793
|
-
textElement.appendChild(more);
|
|
6794
|
-
}
|
|
6795
|
-
displayedSummaryMore = summaryMore;
|
|
6796
6876
|
// Measure the summary's footprint next frame without replacing each member's source text.
|
|
6797
6877
|
this.viewer.scene.requestRender();
|
|
6798
6878
|
}
|
|
@@ -6810,6 +6890,7 @@
|
|
|
6810
6890
|
// The badge participates in layout, so its new width needs another measurement.
|
|
6811
6891
|
this.viewer.scene.requestRender();
|
|
6812
6892
|
}
|
|
6893
|
+
fitIconBackground === null || fitIconBackground === void 0 ? void 0 : fitIconBackground();
|
|
6813
6894
|
if (iconContainer) {
|
|
6814
6895
|
const badgeWidth = countElement.offsetWidth;
|
|
6815
6896
|
const iconWidth = iconElement.offsetWidth;
|
|
@@ -6817,7 +6898,9 @@
|
|
|
6817
6898
|
const clearance = badgeWidth ? (narrow ? badgeWidth / 2 + 2 : Math.max(0, badgeWidth / 2 - iconWidth / 4)) : 0;
|
|
6818
6899
|
countElement.style.left = `calc(100% + ${clearance}px)`;
|
|
6819
6900
|
// Reserve the badge overhang so adjacent text and viewport edges remain clear.
|
|
6820
|
-
|
|
6901
|
+
const overhang = countElement.offsetHeight / 2;
|
|
6902
|
+
iconContainer.style.marginTop = badgeBelow ? "0px" : `${overhang}px`;
|
|
6903
|
+
iconContainer.style.marginBottom = badgeBelow ? `${overhang}px` : "0px";
|
|
6821
6904
|
iconContainer.style.marginRight = `${badgeWidth / 2 + clearance}px`;
|
|
6822
6905
|
}
|
|
6823
6906
|
// Summary and badge changes must fit on their first visible frame, including after resize.
|
|
@@ -6860,19 +6943,26 @@
|
|
|
6860
6943
|
sharedRing.animation = ringAnimation;
|
|
6861
6944
|
}
|
|
6862
6945
|
const radius = ringAnimation.inner > 0 ? ringAnimation.outer : 0;
|
|
6863
|
-
const stem = (leader ? fitLeader(frame.anchorX, frame.anchorY, Math.max(frame.leaderLength, radius ? radius + 4 : 0), ele.offsetWidth / coordinates.scaleX, ele.offsetHeight / coordinates.scaleY, radius) : undefined);
|
|
6946
|
+
const stem = (leader ? (angled ? fitAngledLeader : fitLeader)(frame.anchorX, frame.anchorY, Math.max(frame.leaderLength, radius ? radius + 4 : 0), ele.offsetWidth / coordinates.scaleX, ele.offsetHeight / coordinates.scaleY, radius) : undefined);
|
|
6864
6947
|
const position = { x: (stem || frame).x, y: (stem || frame).y };
|
|
6865
6948
|
const width = ele.offsetWidth / coordinates.scaleX;
|
|
6866
6949
|
const height = ele.offsetHeight / coordinates.scaleY;
|
|
6867
|
-
if (leader &&
|
|
6950
|
+
if (leader && angled) {
|
|
6951
|
+
// The declutter owns the side; the fit only says which one had the room to begin with.
|
|
6952
|
+
const run = Math.max(ANGLED_LEADER_RUN, radius + 4);
|
|
6953
|
+
const side = (_l = (_k = placement.textSide) !== null && _k !== void 0 ? _k : frame.leaderSide) !== null && _l !== void 0 ? _l : "right";
|
|
6954
|
+
const beside = side === "left" ? frame.anchorX - run - width : frame.anchorX + run;
|
|
6955
|
+
position.x = Math.max(0, Math.min(beside, this.viewer.canvas.clientWidth - width));
|
|
6956
|
+
}
|
|
6957
|
+
else if (leader && placement.textSide === "left") {
|
|
6868
6958
|
position.x = Math.max(0, Math.min(frame.anchorX - width, this.viewer.canvas.clientWidth - width));
|
|
6869
6959
|
}
|
|
6870
|
-
const gap = (
|
|
6960
|
+
const gap = (_o = (_m = this.options.pointerAvoidance) === null || _m === void 0 ? void 0 : _m.gap) !== null && _o !== void 0 ? _o : 12;
|
|
6871
6961
|
const containsPointer = (x, y, margin) => {
|
|
6872
6962
|
return pointer && pointer.x >= x - margin && pointer.x <= x + width + margin && pointer.y >= y - margin && pointer.y <= y + height + margin;
|
|
6873
6963
|
};
|
|
6874
6964
|
const passive = !selectOnClick || !this.visualRegister;
|
|
6875
|
-
if (passive && ((
|
|
6965
|
+
if (passive && ((_p = this.options.pointerAvoidance) === null || _p === void 0 ? void 0 : _p.enabled) !== false && pointer &&
|
|
6876
6966
|
(containsPointer(position.x, position.y, gap) || containsPointer(position.x + displacement.x, position.y + displacement.y, gap))) {
|
|
6877
6967
|
if (containsPointer(position.x + displacement.x, position.y + displacement.y, 0)) {
|
|
6878
6968
|
// Choose against the original box and retain the offset until the pointer leaves both boxes.
|
|
@@ -6890,7 +6980,7 @@
|
|
|
6890
6980
|
else {
|
|
6891
6981
|
displacement = { x: 0, y: 0 };
|
|
6892
6982
|
}
|
|
6893
|
-
const nudgeDuration = (
|
|
6983
|
+
const nudgeDuration = (_r = (_q = this.options.pointerAvoidance) === null || _q === void 0 ? void 0 : _q.transitionDuration) !== null && _r !== void 0 ? _r : 200;
|
|
6894
6984
|
const animateNudge = () => {
|
|
6895
6985
|
const progress = now < nudge.start ? 0 : nudgeDuration > 0 ? Math.min(1, (now - nudge.start) / nudgeDuration) : 1;
|
|
6896
6986
|
const eased = progress * progress * (3 - 2 * progress);
|
|
@@ -6906,7 +6996,7 @@
|
|
|
6906
6996
|
fromY: nudge.y,
|
|
6907
6997
|
targetX: displacement.x,
|
|
6908
6998
|
targetY: displacement.y,
|
|
6909
|
-
start: now + ((
|
|
6999
|
+
start: now + ((_t = (_s = this.options.pointerAvoidance) === null || _s === void 0 ? void 0 : _s.delay) !== null && _t !== void 0 ? _t : 180)
|
|
6910
7000
|
};
|
|
6911
7001
|
}
|
|
6912
7002
|
if (animateNudge() < 1 && (nudge.fromX !== nudge.targetX || nudge.fromY !== nudge.targetY)) {
|
|
@@ -6918,7 +7008,7 @@
|
|
|
6918
7008
|
ele.style.top = `${coordinates.y + position.y * coordinates.scaleY}px`;
|
|
6919
7009
|
const clickTarget = content.querySelector('[role="button"]');
|
|
6920
7010
|
if (clickTarget) {
|
|
6921
|
-
clickTarget.setAttribute("aria-label", placement.members.length ? `Select ${placement.entityIds.length} entities` : `Select ${(
|
|
7011
|
+
clickTarget.setAttribute("aria-label", placement.members.length ? `Select ${placement.entityIds.length} entities` : `Select ${(_v = (_u = this.options.text) !== null && _u !== void 0 ? _u : text) !== null && _v !== void 0 ? _v : (_w = this.rego) === null || _w === void 0 ? void 0 : _w.entityId}`);
|
|
6922
7012
|
}
|
|
6923
7013
|
if (leader) {
|
|
6924
7014
|
const nodeRadius = ringAnimation.outer;
|
|
@@ -6941,8 +7031,13 @@
|
|
|
6941
7031
|
anchor.style.opacity = String(opacity * (normalLeader ? 1 : cursorMotion.amount));
|
|
6942
7032
|
anchor.style.zIndex = String(placement.zIndex);
|
|
6943
7033
|
// The stem starts at the rim, never across the transparent centre, even after passive displacement.
|
|
6944
|
-
const
|
|
6945
|
-
const
|
|
7034
|
+
const straightX = Math.max(position.x, Math.min(frame.anchorX, position.x + width));
|
|
7035
|
+
const straightY = frame.anchorY < position.y ? position.y : frame.anchorY > position.y + height ? position.y + height : frame.anchorY;
|
|
7036
|
+
const beside = angled && (frame.anchorX < position.x || frame.anchorX > position.x + width);
|
|
7037
|
+
const elbowY = position.y + height / 2;
|
|
7038
|
+
const endX = beside ? frame.anchorX : straightX;
|
|
7039
|
+
const endY = beside ? elbowY : straightY;
|
|
7040
|
+
const runToX = frame.anchorX < position.x ? position.x : position.x + width;
|
|
6946
7041
|
const dx = endX - frame.anchorX, dy = endY - frame.anchorY;
|
|
6947
7042
|
const length = Math.hypot(dx, dy);
|
|
6948
7043
|
const leaderAngle = Math.atan2(dy, dx);
|
|
@@ -6953,13 +7048,13 @@
|
|
|
6953
7048
|
// Keep the stem inside the 126-degree arc, away from antialiased endpoints.
|
|
6954
7049
|
const arcFraction = 0.35;
|
|
6955
7050
|
const rotationLimit = Math.PI * arcFraction - Math.PI / 30;
|
|
6956
|
-
const targetOffset = hovered ? Math.max(-rotationLimit, Math.min(rotationLimit, wrappedAngle)) : ((
|
|
7051
|
+
const targetOffset = hovered ? Math.max(-rotationLimit, Math.min(rotationLimit, wrappedAngle)) : ((_x = ringAnimation.arcOffset) !== null && _x !== void 0 ? _x : 0);
|
|
6957
7052
|
const targetOpen = cursorMotion.target || (hovered && (ring === null || ring === void 0 ? void 0 : ring.enabled) !== false && targetRadius > 0) ? 1 : 0;
|
|
6958
|
-
const elapsed = Math.min(32, Math.max(0, now - ((
|
|
7053
|
+
const elapsed = Math.min(32, Math.max(0, now - ((_y = ringAnimation.arcTime) !== null && _y !== void 0 ? _y : now)));
|
|
6959
7054
|
const blend = duration > 0 ? 1 - Math.exp(-elapsed / (duration / 3)) : 1;
|
|
6960
7055
|
const approach = (value, target) => Math.abs(value - target) < 0.001 ? target : value + (target - value) * blend;
|
|
6961
|
-
ringAnimation.arcOffset = approach((
|
|
6962
|
-
ringAnimation.arcOpen = approach((
|
|
7056
|
+
ringAnimation.arcOffset = approach((_z = ringAnimation.arcOffset) !== null && _z !== void 0 ? _z : 0, targetOffset);
|
|
7057
|
+
ringAnimation.arcOpen = approach((_0 = ringAnimation.arcOpen) !== null && _0 !== void 0 ? _0 : 0, targetOpen);
|
|
6963
7058
|
ringAnimation.arcTime = now;
|
|
6964
7059
|
if (ringAnimation.arcOffset !== targetOffset || ringAnimation.arcOpen !== targetOpen) {
|
|
6965
7060
|
this.viewer.scene.requestRender();
|
|
@@ -6971,17 +7066,27 @@
|
|
|
6971
7066
|
const cut = Math.min(radius, length);
|
|
6972
7067
|
const startX = frame.anchorX + (length ? dx / length * cut : 0);
|
|
6973
7068
|
const startY = frame.anchorY + (length ? dy / length * cut : 0);
|
|
6974
|
-
const
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
7069
|
+
const draw = (element, fromX, fromY, toX, toY) => {
|
|
7070
|
+
const screenDx = (toX - fromX) * coordinates.scaleX;
|
|
7071
|
+
const screenDy = (toY - fromY) * coordinates.scaleY;
|
|
7072
|
+
element.style.width = `${2 * coordinates.scaleX}px`;
|
|
7073
|
+
element.style.left = `${coordinates.x + (fromX - 1) * coordinates.scaleX}px`;
|
|
7074
|
+
element.style.top = `${coordinates.y + fromY * coordinates.scaleY}px`;
|
|
7075
|
+
element.style.height = `${Math.hypot(screenDx, screenDy)}px`;
|
|
7076
|
+
element.style.transform = `rotate(${Math.atan2(screenDy, screenDx) - Math.PI / 2}rad)`;
|
|
7077
|
+
element.style.boxShadow = radius ? "none" : "0 0 5px rgba(0, 0, 0, 0.3)";
|
|
7078
|
+
element.style.transformOrigin = "top center";
|
|
7079
|
+
element.style.opacity = String(opacity * (normalLeader ? 1 : cursorMotion.amount));
|
|
7080
|
+
element.style.zIndex = String(placement.zIndex);
|
|
7081
|
+
};
|
|
7082
|
+
draw(lineEle, startX, startY, endX, endY);
|
|
7083
|
+
if (runEle) {
|
|
7084
|
+
// Overlap the corner by the stem's own width so the elbow has no notch in it.
|
|
7085
|
+
const overlap = frame.anchorX < runToX ? -1 : 1;
|
|
7086
|
+
runEle.style.display = beside ? "block" : "none";
|
|
7087
|
+
if (beside)
|
|
7088
|
+
draw(runEle, endX + overlap, endY, runToX, endY);
|
|
7089
|
+
}
|
|
6985
7090
|
}
|
|
6986
7091
|
};
|
|
6987
7092
|
ele.style.display = "flex";
|
|
@@ -7006,7 +7111,7 @@
|
|
|
7006
7111
|
* Removes label from the viewer and unsubscribes from events.
|
|
7007
7112
|
*/
|
|
7008
7113
|
removeLabel() {
|
|
7009
|
-
var _a;
|
|
7114
|
+
var _a, _b;
|
|
7010
7115
|
(_a = this.anchor) === null || _a === void 0 ? void 0 : _a.remove();
|
|
7011
7116
|
this.anchor = null;
|
|
7012
7117
|
if (this.label &&
|
|
@@ -7018,6 +7123,8 @@
|
|
|
7018
7123
|
this.line.parentElement.removeChild(this.line);
|
|
7019
7124
|
this.line = null;
|
|
7020
7125
|
}
|
|
7126
|
+
(_b = this.leaderRun) === null || _b === void 0 ? void 0 : _b.remove();
|
|
7127
|
+
this.leaderRun = null;
|
|
7021
7128
|
if (this.renderRemoval) {
|
|
7022
7129
|
this.renderRemoval();
|
|
7023
7130
|
this.renderRemoval = null;
|
|
@@ -7140,10 +7247,59 @@
|
|
|
7140
7247
|
};
|
|
7141
7248
|
}
|
|
7142
7249
|
EntityLabelGroup.FromEntity = FromEntity;
|
|
7250
|
+
/**
|
|
7251
|
+
* Returns if we need to resolve Entity data to create the label data.
|
|
7252
|
+
*/
|
|
7253
|
+
function NeedsEntityData(options) {
|
|
7254
|
+
var _a;
|
|
7255
|
+
if (!options) {
|
|
7256
|
+
return false;
|
|
7257
|
+
}
|
|
7258
|
+
if ((_a = options.attributes) === null || _a === void 0 ? void 0 : _a.length) {
|
|
7259
|
+
return true;
|
|
7260
|
+
}
|
|
7261
|
+
return [
|
|
7262
|
+
options.text, options.icon, options.iconUrl, options.iconClass,
|
|
7263
|
+
options.iconColor, options.iconStatus, options.iconPriority, options.iconScale
|
|
7264
|
+
].some(Array.isArray);
|
|
7265
|
+
}
|
|
7266
|
+
EntityLabelGroup.NeedsEntityData = NeedsEntityData;
|
|
7267
|
+
// How many entities to read at once, so a long hand-picked list does not arrive as a burst.
|
|
7268
|
+
const HYDRATE_AT_ONCE = 8;
|
|
7269
|
+
/*
|
|
7270
|
+
* Reads the entities behind items that name one without carrying it.
|
|
7271
|
+
*/
|
|
7272
|
+
async function Hydrate(items, api, signal) {
|
|
7273
|
+
if (!api) {
|
|
7274
|
+
return items;
|
|
7275
|
+
}
|
|
7276
|
+
const hydrated = items.slice();
|
|
7277
|
+
for (let start = 0; start < hydrated.length; start += HYDRATE_AT_ONCE) {
|
|
7278
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
7279
|
+
return hydrated;
|
|
7280
|
+
}
|
|
7281
|
+
await Promise.all(hydrated.slice(start, start + HYDRATE_AT_ONCE).map(async (item, at) => {
|
|
7282
|
+
if (!(item === null || item === void 0 ? void 0 : item.entityId) || item.entity) {
|
|
7283
|
+
return;
|
|
7284
|
+
}
|
|
7285
|
+
try {
|
|
7286
|
+
const { entity } = await BModels.Entity.Get({ api, entityId: item.entityId, migrated: true });
|
|
7287
|
+
if (entity) {
|
|
7288
|
+
hydrated[start + at] = { ...item, entity };
|
|
7289
|
+
}
|
|
7290
|
+
}
|
|
7291
|
+
catch {
|
|
7292
|
+
// Rip.
|
|
7293
|
+
}
|
|
7294
|
+
}));
|
|
7295
|
+
}
|
|
7296
|
+
return hydrated;
|
|
7297
|
+
}
|
|
7298
|
+
EntityLabelGroup.Hydrate = Hydrate;
|
|
7143
7299
|
/*
|
|
7144
7300
|
* Uses the existing DataLab grammar, discarding actions and projections that cannot return Entities.
|
|
7145
7301
|
*/
|
|
7146
|
-
async function Loader(source, api, signal) {
|
|
7302
|
+
async function Loader(source, api, signal, hydrate) {
|
|
7147
7303
|
var _a;
|
|
7148
7304
|
var _b;
|
|
7149
7305
|
if (source.type === "provider") {
|
|
@@ -7155,7 +7311,13 @@
|
|
|
7155
7311
|
if (!Array.isArray(items)) {
|
|
7156
7312
|
throw new Error("Label JSON must be an array of label items");
|
|
7157
7313
|
}
|
|
7158
|
-
return async (offset, limit) =>
|
|
7314
|
+
return async (offset, limit, signal) => {
|
|
7315
|
+
const page = items.slice(offset, offset + limit);
|
|
7316
|
+
return {
|
|
7317
|
+
items: hydrate ? await Hydrate(page, api, signal) : page,
|
|
7318
|
+
hasMore: offset + limit < items.length
|
|
7319
|
+
};
|
|
7320
|
+
};
|
|
7159
7321
|
}
|
|
7160
7322
|
if (!api) {
|
|
7161
7323
|
throw new Error("DataLab label sources require API getters on the visual register");
|
|
@@ -7284,7 +7446,7 @@
|
|
|
7284
7446
|
const items = new Map();
|
|
7285
7447
|
let truncated = false;
|
|
7286
7448
|
try {
|
|
7287
|
-
const load = await Loader(definition.source, (_g = this.register.ApiGetters) === null || _g === void 0 ? void 0 : _g.GetBruceApi(), controller.signal);
|
|
7449
|
+
const load = await Loader(definition.source, (_g = this.register.ApiGetters) === null || _g === void 0 ? void 0 : _g.GetBruceApi(), controller.signal, NeedsEntityData(definition.options));
|
|
7288
7450
|
let offset = 0;
|
|
7289
7451
|
for (let pageNumber = 0;; pageNumber++) {
|
|
7290
7452
|
if (controller.signal.aborted || this.register.Disposed) {
|
|
@@ -7490,10 +7652,11 @@
|
|
|
7490
7652
|
this.pending.delete(id);
|
|
7491
7653
|
const group = this.active.get(id);
|
|
7492
7654
|
if (!group) {
|
|
7655
|
+
// Nothing to unindex. Say so only if there was a definition to forget.
|
|
7493
7656
|
if (known) {
|
|
7494
7657
|
this.notify();
|
|
7495
|
-
return;
|
|
7496
7658
|
}
|
|
7659
|
+
return;
|
|
7497
7660
|
}
|
|
7498
7661
|
this.unindex(id);
|
|
7499
7662
|
this.active.delete(id);
|
|
@@ -50068,7 +50231,7 @@ void main() {
|
|
|
50068
50231
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
50069
50232
|
})(exports.StyleUtils || (exports.StyleUtils = {}));
|
|
50070
50233
|
|
|
50071
|
-
const VERSION = "7.4.
|
|
50234
|
+
const VERSION = "7.4.2";
|
|
50072
50235
|
/**
|
|
50073
50236
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
50074
50237
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|