@mapvx/web-js 3.1.0-dev.2 → 3.1.0
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/cjs/controllers/routeController.js +0 -13
- package/dist/cjs/controllers/routeController.js.map +1 -1
- package/dist/cjs/domain/models/mapConfig.js +1 -13
- package/dist/cjs/domain/models/mapConfig.js.map +1 -1
- package/dist/cjs/domain/models/marker.js +82 -147
- package/dist/cjs/domain/models/marker.js.map +1 -1
- package/dist/cjs/index.js +1 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/logger/sentry.js +1 -1
- package/dist/cjs/map/map.js +3 -41
- package/dist/cjs/map/map.js.map +1 -1
- package/dist/es/controllers/routeController.d.ts +0 -7
- package/dist/es/controllers/routeController.d.ts.map +1 -1
- package/dist/es/controllers/routeController.js +0 -13
- package/dist/es/controllers/routeController.js.map +1 -1
- package/dist/es/domain/models/mapConfig.d.ts +0 -73
- package/dist/es/domain/models/mapConfig.d.ts.map +1 -1
- package/dist/es/domain/models/mapConfig.js +0 -12
- package/dist/es/domain/models/mapConfig.js.map +1 -1
- package/dist/es/domain/models/marker.d.ts +1 -232
- package/dist/es/domain/models/marker.d.ts.map +1 -1
- package/dist/es/domain/models/marker.js +82 -146
- package/dist/es/domain/models/marker.js.map +1 -1
- package/dist/es/index.d.ts +2 -2
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/index.js +1 -1
- package/dist/es/index.js.map +1 -1
- package/dist/es/logger/sentry.js +1 -1
- package/dist/es/map/map.d.ts +1 -15
- package/dist/es/map/map.d.ts.map +1 -1
- package/dist/es/map/map.js +4 -42
- package/dist/es/map/map.js.map +1 -1
- package/dist/umd/index.js +130 -828
- package/dist/umd/index.js.map +1 -1
- package/dist/umd/styles.css +19 -45
- package/dist/umd/styles.css.map +1 -1
- package/package.json +1 -1
- package/dist/cjs/controllers/markerLayoutController.js +0 -337
- package/dist/cjs/controllers/markerLayoutController.js.map +0 -1
- package/dist/es/controllers/markerLayoutController.d.ts +0 -140
- package/dist/es/controllers/markerLayoutController.d.ts.map +0 -1
- package/dist/es/controllers/markerLayoutController.js +0 -329
- package/dist/es/controllers/markerLayoutController.js.map +0 -1
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MarkerLayoutController = exports.FALLBACK_ORDER = exports.ANCHOR_FRACTIONS = void 0;
|
|
4
|
-
exports.computeIconRect = computeIconRect;
|
|
5
|
-
exports.computeCandidateRect = computeCandidateRect;
|
|
6
|
-
exports.expandRect = expandRect;
|
|
7
|
-
exports.rectsIntersect = rectsIntersect;
|
|
8
|
-
const marker_1 = require("../domain/models/marker");
|
|
9
|
-
/**
|
|
10
|
-
* Fraction of the icon's own box, along each axis, that MapLibre's Marker
|
|
11
|
-
* anchor math (`translate(-x%, -y%)`) aligns to the geodetic point. Mirrors
|
|
12
|
-
* MapLibre's own `anchorTranslate` table so the collision math agrees with
|
|
13
|
-
* what's actually on screen.
|
|
14
|
-
*/
|
|
15
|
-
exports.ANCHOR_FRACTIONS = {
|
|
16
|
-
center: { fx: 0.5, fy: 0.5 },
|
|
17
|
-
top: { fx: 0.5, fy: 0 },
|
|
18
|
-
bottom: { fx: 0.5, fy: 1 },
|
|
19
|
-
left: { fx: 0, fy: 0.5 },
|
|
20
|
-
right: { fx: 1, fy: 0.5 },
|
|
21
|
-
"top-left": { fx: 0, fy: 0 },
|
|
22
|
-
"top-right": { fx: 1, fy: 0 },
|
|
23
|
-
"bottom-left": { fx: 0, fy: 1 },
|
|
24
|
-
"bottom-right": { fx: 1, fy: 1 },
|
|
25
|
-
};
|
|
26
|
-
/** Candidate order tried when a marker's preferred side is unavailable. */
|
|
27
|
-
exports.FALLBACK_ORDER = [
|
|
28
|
-
marker_1.TextPosition.right,
|
|
29
|
-
marker_1.TextPosition.top,
|
|
30
|
-
marker_1.TextPosition.left,
|
|
31
|
-
marker_1.TextPosition.bottom,
|
|
32
|
-
];
|
|
33
|
-
/** Builds the icon's on-screen rect from its projected point, size and anchor. */
|
|
34
|
-
function computeIconRect(screen, iconSize, anchor) {
|
|
35
|
-
var _a;
|
|
36
|
-
const { fx, fy } = (_a = exports.ANCHOR_FRACTIONS[anchor]) !== null && _a !== void 0 ? _a : exports.ANCHOR_FRACTIONS.center;
|
|
37
|
-
return {
|
|
38
|
-
left: screen.x - fx * iconSize.width,
|
|
39
|
-
top: screen.y - fy * iconSize.height,
|
|
40
|
-
width: iconSize.width,
|
|
41
|
-
height: iconSize.height,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Builds a candidate label rect for one side of an icon. Mirrors the CSS in
|
|
46
|
-
* `styles.css` (`.text-container.right/left/top/bottom`) exactly, so a
|
|
47
|
-
* position the algorithm picks as collision-free renders collision-free.
|
|
48
|
-
*/
|
|
49
|
-
function computeCandidateRect(iconRect, labelSize, position, gapPx, verticalGapPx) {
|
|
50
|
-
switch (position) {
|
|
51
|
-
case marker_1.TextPosition.left:
|
|
52
|
-
return {
|
|
53
|
-
left: iconRect.left - gapPx - labelSize.width,
|
|
54
|
-
top: iconRect.top + iconRect.height / 2 - labelSize.height / 2,
|
|
55
|
-
width: labelSize.width,
|
|
56
|
-
height: labelSize.height,
|
|
57
|
-
};
|
|
58
|
-
case marker_1.TextPosition.top:
|
|
59
|
-
return {
|
|
60
|
-
left: iconRect.left + iconRect.width / 2 - labelSize.width / 2,
|
|
61
|
-
top: iconRect.top - verticalGapPx - labelSize.height,
|
|
62
|
-
width: labelSize.width,
|
|
63
|
-
height: labelSize.height,
|
|
64
|
-
};
|
|
65
|
-
case marker_1.TextPosition.bottom:
|
|
66
|
-
return {
|
|
67
|
-
left: iconRect.left + iconRect.width / 2 - labelSize.width / 2,
|
|
68
|
-
top: iconRect.top + iconRect.height + verticalGapPx,
|
|
69
|
-
width: labelSize.width,
|
|
70
|
-
height: labelSize.height,
|
|
71
|
-
};
|
|
72
|
-
case marker_1.TextPosition.right:
|
|
73
|
-
default:
|
|
74
|
-
return {
|
|
75
|
-
left: iconRect.left + iconRect.width + gapPx,
|
|
76
|
-
top: iconRect.top + iconRect.height / 2 - labelSize.height / 2,
|
|
77
|
-
width: labelSize.width,
|
|
78
|
-
height: labelSize.height,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/** Expands a rect by `padding` on every side. */
|
|
83
|
-
function expandRect(rect, padding) {
|
|
84
|
-
return {
|
|
85
|
-
left: rect.left - padding,
|
|
86
|
-
top: rect.top - padding,
|
|
87
|
-
width: rect.width + 2 * padding,
|
|
88
|
-
height: rect.height + 2 * padding,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
/** Standard AABB intersection test. */
|
|
92
|
-
function rectsIntersect(a, b) {
|
|
93
|
-
return (a.left < b.left + b.width &&
|
|
94
|
-
a.left + a.width > b.left &&
|
|
95
|
-
a.top < b.top + b.height &&
|
|
96
|
-
a.top + a.height > b.top);
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Automatic collision avoidance for marker text labels: keeps a marker's
|
|
100
|
-
* icon fixed while moving (or hiding) its label to avoid overlapping
|
|
101
|
-
* neighboring markers' icons/labels, similar to Google Maps' label
|
|
102
|
-
* placement. See {@link MarkerLayoutConfig}.
|
|
103
|
-
*
|
|
104
|
-
* Not part of the public SDK surface — owned and driven entirely by
|
|
105
|
-
* {@link InternalMapVXMap}, mirroring `RouteController`.
|
|
106
|
-
*/
|
|
107
|
-
class MarkerLayoutController {
|
|
108
|
-
constructor(map, config) {
|
|
109
|
-
this.labelSizeCache = new WeakMap();
|
|
110
|
-
this.iconSizeCache = new WeakMap();
|
|
111
|
-
this.lastAppliedState = new WeakMap();
|
|
112
|
-
this.attached = false;
|
|
113
|
-
this.mapvxMap = map;
|
|
114
|
-
this.config = config;
|
|
115
|
-
this.boundOnMove = () => this.scheduleRelayout();
|
|
116
|
-
}
|
|
117
|
-
get map() {
|
|
118
|
-
return this.mapvxMap.map;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Starts listening for camera movement. Safe to call once the underlying
|
|
122
|
-
* MapLibre `Map` instance exists; a single `"move"` listener covers pan,
|
|
123
|
-
* zoom, rotate, pitch and `resize()`.
|
|
124
|
-
*/
|
|
125
|
-
attach() {
|
|
126
|
-
if (this.attached)
|
|
127
|
-
return;
|
|
128
|
-
this.attached = true;
|
|
129
|
-
this.map.on("move", this.boundOnMove);
|
|
130
|
-
this.remeasureWhenFontsLoad();
|
|
131
|
-
this.scheduleRelayout();
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Publishes the configured gaps and label width cap as CSS custom
|
|
135
|
-
* properties, which `styles.css` reads to offset labels from their icon.
|
|
136
|
-
* Without this the stylesheet would keep its hardcoded defaults while the
|
|
137
|
-
* collision math used the configured values, so any custom `gapPx` /
|
|
138
|
-
* `verticalGapPx` would produce placements this controller believes are
|
|
139
|
-
* collision-free but that visibly overlap on screen.
|
|
140
|
-
*
|
|
141
|
-
* Called with the map's own container, so every marker MapLibre mounts
|
|
142
|
-
* inside it inherits the values.
|
|
143
|
-
*/
|
|
144
|
-
applyLayoutVariables(container) {
|
|
145
|
-
container.style.setProperty("--mapvx-label-gap", `${this.config.gapPx}px`);
|
|
146
|
-
container.style.setProperty("--mapvx-label-vertical-gap", `${this.config.verticalGapPx}px`);
|
|
147
|
-
container.style.setProperty("--mapvx-label-max-width", `${this.config.maxLabelWidthPx}px`);
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* A label measured before its web font finishes loading is measured in the
|
|
151
|
-
* fallback font, and that wrong footprint would otherwise be cached for
|
|
152
|
-
* the marker's lifetime. Drop every measurement once fonts settle.
|
|
153
|
-
*/
|
|
154
|
-
remeasureWhenFontsLoad() {
|
|
155
|
-
const fonts = document.fonts;
|
|
156
|
-
if (!fonts)
|
|
157
|
-
return;
|
|
158
|
-
fonts.ready
|
|
159
|
-
.then(() => {
|
|
160
|
-
if (!this.attached)
|
|
161
|
-
return;
|
|
162
|
-
this.labelSizeCache = new WeakMap();
|
|
163
|
-
this.iconSizeCache = new WeakMap();
|
|
164
|
-
this.scheduleRelayout();
|
|
165
|
-
})
|
|
166
|
-
.catch(() => {
|
|
167
|
-
// Font loading failing is not a layout error: the measurements
|
|
168
|
-
// already taken in the fallback font stay in effect.
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
/** Stops listening and cancels any pending layout pass. */
|
|
172
|
-
destroy() {
|
|
173
|
-
if (this.attached) {
|
|
174
|
-
this.map.off("move", this.boundOnMove);
|
|
175
|
-
this.attached = false;
|
|
176
|
-
}
|
|
177
|
-
if (this.rafHandle !== undefined) {
|
|
178
|
-
cancelAnimationFrame(this.rafHandle);
|
|
179
|
-
this.rafHandle = undefined;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Drops everything cached for a marker, e.g. after its text/content
|
|
184
|
-
* changed.
|
|
185
|
-
*
|
|
186
|
-
* The last applied decision has to go too: rebuilding a marker's DOM
|
|
187
|
-
* replaces its `.text-container` with a fresh one carrying the preferred
|
|
188
|
-
* side and no `visibility`, so a decision remembered from the old element
|
|
189
|
-
* would make {@link applyDecisions} short-circuit and leave the new label
|
|
190
|
-
* on the wrong side — or visible when it should be hidden.
|
|
191
|
-
*/
|
|
192
|
-
invalidateMarker(marker) {
|
|
193
|
-
this.labelSizeCache.delete(marker);
|
|
194
|
-
this.iconSizeCache.delete(marker);
|
|
195
|
-
this.lastAppliedState.delete(marker);
|
|
196
|
-
}
|
|
197
|
-
/** Coalesces repeated calls into a single layout pass per animation frame. */
|
|
198
|
-
scheduleRelayout() {
|
|
199
|
-
if (!this.config.enabled || this.rafHandle !== undefined)
|
|
200
|
-
return;
|
|
201
|
-
this.rafHandle = requestAnimationFrame(() => {
|
|
202
|
-
this.rafHandle = undefined;
|
|
203
|
-
this.performLayout();
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
performLayout() {
|
|
207
|
-
// Guards against a relayout firing before the underlying MapLibre `map`
|
|
208
|
-
// exists (e.g. a marker added before the "load" event) — `attach()`
|
|
209
|
-
// schedules its own initial pass once it's safe to touch `this.map`.
|
|
210
|
-
if (!this.attached)
|
|
211
|
-
return;
|
|
212
|
-
const markers = this.mapvxMap.getMarkers();
|
|
213
|
-
if (markers.length === 0)
|
|
214
|
-
return;
|
|
215
|
-
const container = this.map.getContainer();
|
|
216
|
-
const viewportWidth = container.clientWidth;
|
|
217
|
-
const viewportHeight = container.clientHeight;
|
|
218
|
-
const cullMargin = this.config.maxLabelWidthPx + Math.max(this.config.gapPx, this.config.verticalGapPx);
|
|
219
|
-
const entries = this.readMarkers(markers, viewportWidth, viewportHeight, cullMargin);
|
|
220
|
-
const decisions = this.decidePlacements(entries);
|
|
221
|
-
this.applyDecisions(decisions);
|
|
222
|
-
}
|
|
223
|
-
/** Read phase: project + measure, no writes. Culls markers fully outside the viewport. */
|
|
224
|
-
readMarkers(markers, viewportWidth, viewportHeight, cullMargin) {
|
|
225
|
-
const entries = [];
|
|
226
|
-
for (const marker of markers) {
|
|
227
|
-
if (!marker.getElement().isConnected)
|
|
228
|
-
continue;
|
|
229
|
-
const screen = this.map.project(marker.getLngLat());
|
|
230
|
-
const iconRect = computeIconRect(screen, this.resolveIconSize(marker), marker.anchorType);
|
|
231
|
-
const outOfViewport = iconRect.left + iconRect.width < -cullMargin ||
|
|
232
|
-
iconRect.left > viewportWidth + cullMargin ||
|
|
233
|
-
iconRect.top + iconRect.height < -cullMargin ||
|
|
234
|
-
iconRect.top > viewportHeight + cullMargin;
|
|
235
|
-
if (outOfViewport)
|
|
236
|
-
continue;
|
|
237
|
-
entries.push({ marker, iconRect, labelSize: this.resolveLabelSize(marker) });
|
|
238
|
-
}
|
|
239
|
-
return entries;
|
|
240
|
-
}
|
|
241
|
-
resolveLabelSize(marker) {
|
|
242
|
-
const textEl = marker.textContainerEl;
|
|
243
|
-
if (!textEl)
|
|
244
|
-
return undefined;
|
|
245
|
-
return this.measureCached(this.labelSizeCache, marker, textEl);
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* The icon's box. Markers built from a caller-supplied `element` with no
|
|
249
|
-
* declared `iconProperties` are measured from the DOM, since their real
|
|
250
|
-
* size is whatever that element renders at; everyone else's box is exactly
|
|
251
|
-
* what `MarkerUtils.createMarkerElement` pinned it to.
|
|
252
|
-
*/
|
|
253
|
-
resolveIconSize(marker) {
|
|
254
|
-
var _a;
|
|
255
|
-
if (!marker.measureIconFromDom)
|
|
256
|
-
return marker.iconSize;
|
|
257
|
-
return (_a = this.measureCached(this.iconSizeCache, marker, marker.getElement())) !== null && _a !== void 0 ? _a : marker.iconSize;
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Measures an element once and remembers it. A zero measurement is
|
|
261
|
-
* returned but never cached: it means the element isn't laid out yet (a
|
|
262
|
-
* `display: none` ancestor, a first pass before the web font loads), and
|
|
263
|
-
* caching it would freeze that marker's footprint at nothing for the rest
|
|
264
|
-
* of its life.
|
|
265
|
-
*/
|
|
266
|
-
measureCached(cache, marker, element) {
|
|
267
|
-
const cached = cache.get(marker);
|
|
268
|
-
if (cached)
|
|
269
|
-
return cached;
|
|
270
|
-
const measured = { width: element.offsetWidth, height: element.offsetHeight };
|
|
271
|
-
if (measured.width <= 0 || measured.height <= 0)
|
|
272
|
-
return undefined;
|
|
273
|
-
cache.set(marker, measured);
|
|
274
|
-
return measured;
|
|
275
|
-
}
|
|
276
|
-
/** Compute phase: pure, no DOM access. Icons always block; labels negotiate a side or hide. */
|
|
277
|
-
decidePlacements(entries) {
|
|
278
|
-
const placedLabels = [];
|
|
279
|
-
const withLabel = entries.filter(hasLabelSize);
|
|
280
|
-
// Stable sort (spec-guaranteed): equal priority keeps insertion order.
|
|
281
|
-
withLabel.sort((a, b) => b.marker.labelPriority - a.marker.labelPriority);
|
|
282
|
-
const decisions = new Map();
|
|
283
|
-
for (const entry of withLabel) {
|
|
284
|
-
const order = [
|
|
285
|
-
entry.marker.preferredTextPosition,
|
|
286
|
-
...exports.FALLBACK_ORDER.filter((position) => position !== entry.marker.preferredTextPosition),
|
|
287
|
-
];
|
|
288
|
-
const fit = order
|
|
289
|
-
.map((position) => ({
|
|
290
|
-
position,
|
|
291
|
-
rect: computeCandidateRect(entry.iconRect, entry.labelSize, position, this.config.gapPx, this.config.verticalGapPx),
|
|
292
|
-
}))
|
|
293
|
-
.find(({ rect }) => !this.collides(rect, entry.marker, entries, placedLabels));
|
|
294
|
-
if (fit) {
|
|
295
|
-
placedLabels.push(fit.rect);
|
|
296
|
-
decisions.set(entry.marker, { position: fit.position, hidden: false });
|
|
297
|
-
}
|
|
298
|
-
else {
|
|
299
|
-
decisions.set(entry.marker, { position: entry.marker.preferredTextPosition, hidden: true });
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
return decisions;
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Whether a candidate label rect clashes with any other marker's icon or
|
|
306
|
-
* with a label already placed this pass.
|
|
307
|
-
*
|
|
308
|
-
* A label's own icon is deliberately excluded: `gapPx`/`verticalGapPx`
|
|
309
|
-
* already define the spacing to it, and `paddingPx` is breathing room
|
|
310
|
-
* against *neighbors*. Counting the own icon here would make top/bottom
|
|
311
|
-
* impossible for every marker as soon as `paddingPx` exceeded
|
|
312
|
-
* `verticalGapPx` (4 vs 4 by default) — and at `paddingPx: 10` would hide
|
|
313
|
-
* every label on the map.
|
|
314
|
-
*/
|
|
315
|
-
collides(rect, self, entries, placedLabels) {
|
|
316
|
-
const padded = expandRect(rect, this.config.paddingPx);
|
|
317
|
-
return (entries.some((other) => other.marker !== self && rectsIntersect(padded, other.iconRect)) ||
|
|
318
|
-
placedLabels.some((label) => rectsIntersect(padded, label)));
|
|
319
|
-
}
|
|
320
|
-
/** Write phase: only touches the DOM for markers whose decision actually changed. */
|
|
321
|
-
applyDecisions(decisions) {
|
|
322
|
-
decisions.forEach((decision, marker) => {
|
|
323
|
-
const last = this.lastAppliedState.get(marker);
|
|
324
|
-
if (last && last.position === decision.position && last.hidden === decision.hidden)
|
|
325
|
-
return;
|
|
326
|
-
if (marker.textContainerEl) {
|
|
327
|
-
marker_1.MarkerUtils.applyTextPosition(marker.textContainerEl, decision.position, decision.hidden);
|
|
328
|
-
}
|
|
329
|
-
this.lastAppliedState.set(marker, decision);
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
exports.MarkerLayoutController = MarkerLayoutController;
|
|
334
|
-
function hasLabelSize(entry) {
|
|
335
|
-
return entry.labelSize !== undefined;
|
|
336
|
-
}
|
|
337
|
-
//# sourceMappingURL=markerLayoutController.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"markerLayoutController.js","sourceRoot":"","sources":["../../../src/controllers/markerLayoutController.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { type PositionAnchor } from "maplibre-gl";
|
|
2
|
-
import { type MarkerLayoutConfig } from "../domain/models/mapConfig";
|
|
3
|
-
import { type MarkerAttribute, TextPosition } from "../domain/models/marker";
|
|
4
|
-
import { type InternalMapVXMap } from "../map/map";
|
|
5
|
-
/** Axis-aligned box in screen (CSS pixel) space. */
|
|
6
|
-
export interface Rect {
|
|
7
|
-
left: number;
|
|
8
|
-
top: number;
|
|
9
|
-
width: number;
|
|
10
|
-
height: number;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Fraction of the icon's own box, along each axis, that MapLibre's Marker
|
|
14
|
-
* anchor math (`translate(-x%, -y%)`) aligns to the geodetic point. Mirrors
|
|
15
|
-
* MapLibre's own `anchorTranslate` table so the collision math agrees with
|
|
16
|
-
* what's actually on screen.
|
|
17
|
-
*/
|
|
18
|
-
export declare const ANCHOR_FRACTIONS: Record<PositionAnchor, {
|
|
19
|
-
fx: number;
|
|
20
|
-
fy: number;
|
|
21
|
-
}>;
|
|
22
|
-
/** Candidate order tried when a marker's preferred side is unavailable. */
|
|
23
|
-
export declare const FALLBACK_ORDER: TextPosition[];
|
|
24
|
-
/** Builds the icon's on-screen rect from its projected point, size and anchor. */
|
|
25
|
-
export declare function computeIconRect(screen: {
|
|
26
|
-
x: number;
|
|
27
|
-
y: number;
|
|
28
|
-
}, iconSize: {
|
|
29
|
-
width: number;
|
|
30
|
-
height: number;
|
|
31
|
-
}, anchor: PositionAnchor): Rect;
|
|
32
|
-
/**
|
|
33
|
-
* Builds a candidate label rect for one side of an icon. Mirrors the CSS in
|
|
34
|
-
* `styles.css` (`.text-container.right/left/top/bottom`) exactly, so a
|
|
35
|
-
* position the algorithm picks as collision-free renders collision-free.
|
|
36
|
-
*/
|
|
37
|
-
export declare function computeCandidateRect(iconRect: Rect, labelSize: {
|
|
38
|
-
width: number;
|
|
39
|
-
height: number;
|
|
40
|
-
}, position: TextPosition, gapPx: number, verticalGapPx: number): Rect;
|
|
41
|
-
/** Expands a rect by `padding` on every side. */
|
|
42
|
-
export declare function expandRect(rect: Rect, padding: number): Rect;
|
|
43
|
-
/** Standard AABB intersection test. */
|
|
44
|
-
export declare function rectsIntersect(a: Rect, b: Rect): boolean;
|
|
45
|
-
/**
|
|
46
|
-
* Automatic collision avoidance for marker text labels: keeps a marker's
|
|
47
|
-
* icon fixed while moving (or hiding) its label to avoid overlapping
|
|
48
|
-
* neighboring markers' icons/labels, similar to Google Maps' label
|
|
49
|
-
* placement. See {@link MarkerLayoutConfig}.
|
|
50
|
-
*
|
|
51
|
-
* Not part of the public SDK surface — owned and driven entirely by
|
|
52
|
-
* {@link InternalMapVXMap}, mirroring `RouteController`.
|
|
53
|
-
*/
|
|
54
|
-
export declare class MarkerLayoutController {
|
|
55
|
-
private readonly mapvxMap;
|
|
56
|
-
private readonly config;
|
|
57
|
-
private labelSizeCache;
|
|
58
|
-
private iconSizeCache;
|
|
59
|
-
private readonly lastAppliedState;
|
|
60
|
-
private readonly boundOnMove;
|
|
61
|
-
private rafHandle;
|
|
62
|
-
private attached;
|
|
63
|
-
constructor(map: InternalMapVXMap, config: Required<MarkerLayoutConfig>);
|
|
64
|
-
private get map();
|
|
65
|
-
/**
|
|
66
|
-
* Starts listening for camera movement. Safe to call once the underlying
|
|
67
|
-
* MapLibre `Map` instance exists; a single `"move"` listener covers pan,
|
|
68
|
-
* zoom, rotate, pitch and `resize()`.
|
|
69
|
-
*/
|
|
70
|
-
attach(): void;
|
|
71
|
-
/**
|
|
72
|
-
* Publishes the configured gaps and label width cap as CSS custom
|
|
73
|
-
* properties, which `styles.css` reads to offset labels from their icon.
|
|
74
|
-
* Without this the stylesheet would keep its hardcoded defaults while the
|
|
75
|
-
* collision math used the configured values, so any custom `gapPx` /
|
|
76
|
-
* `verticalGapPx` would produce placements this controller believes are
|
|
77
|
-
* collision-free but that visibly overlap on screen.
|
|
78
|
-
*
|
|
79
|
-
* Called with the map's own container, so every marker MapLibre mounts
|
|
80
|
-
* inside it inherits the values.
|
|
81
|
-
*/
|
|
82
|
-
applyLayoutVariables(container: HTMLElement): void;
|
|
83
|
-
/**
|
|
84
|
-
* A label measured before its web font finishes loading is measured in the
|
|
85
|
-
* fallback font, and that wrong footprint would otherwise be cached for
|
|
86
|
-
* the marker's lifetime. Drop every measurement once fonts settle.
|
|
87
|
-
*/
|
|
88
|
-
private remeasureWhenFontsLoad;
|
|
89
|
-
/** Stops listening and cancels any pending layout pass. */
|
|
90
|
-
destroy(): void;
|
|
91
|
-
/**
|
|
92
|
-
* Drops everything cached for a marker, e.g. after its text/content
|
|
93
|
-
* changed.
|
|
94
|
-
*
|
|
95
|
-
* The last applied decision has to go too: rebuilding a marker's DOM
|
|
96
|
-
* replaces its `.text-container` with a fresh one carrying the preferred
|
|
97
|
-
* side and no `visibility`, so a decision remembered from the old element
|
|
98
|
-
* would make {@link applyDecisions} short-circuit and leave the new label
|
|
99
|
-
* on the wrong side — or visible when it should be hidden.
|
|
100
|
-
*/
|
|
101
|
-
invalidateMarker(marker: MarkerAttribute): void;
|
|
102
|
-
/** Coalesces repeated calls into a single layout pass per animation frame. */
|
|
103
|
-
scheduleRelayout(): void;
|
|
104
|
-
private performLayout;
|
|
105
|
-
/** Read phase: project + measure, no writes. Culls markers fully outside the viewport. */
|
|
106
|
-
private readMarkers;
|
|
107
|
-
private resolveLabelSize;
|
|
108
|
-
/**
|
|
109
|
-
* The icon's box. Markers built from a caller-supplied `element` with no
|
|
110
|
-
* declared `iconProperties` are measured from the DOM, since their real
|
|
111
|
-
* size is whatever that element renders at; everyone else's box is exactly
|
|
112
|
-
* what `MarkerUtils.createMarkerElement` pinned it to.
|
|
113
|
-
*/
|
|
114
|
-
private resolveIconSize;
|
|
115
|
-
/**
|
|
116
|
-
* Measures an element once and remembers it. A zero measurement is
|
|
117
|
-
* returned but never cached: it means the element isn't laid out yet (a
|
|
118
|
-
* `display: none` ancestor, a first pass before the web font loads), and
|
|
119
|
-
* caching it would freeze that marker's footprint at nothing for the rest
|
|
120
|
-
* of its life.
|
|
121
|
-
*/
|
|
122
|
-
private measureCached;
|
|
123
|
-
/** Compute phase: pure, no DOM access. Icons always block; labels negotiate a side or hide. */
|
|
124
|
-
private decidePlacements;
|
|
125
|
-
/**
|
|
126
|
-
* Whether a candidate label rect clashes with any other marker's icon or
|
|
127
|
-
* with a label already placed this pass.
|
|
128
|
-
*
|
|
129
|
-
* A label's own icon is deliberately excluded: `gapPx`/`verticalGapPx`
|
|
130
|
-
* already define the spacing to it, and `paddingPx` is breathing room
|
|
131
|
-
* against *neighbors*. Counting the own icon here would make top/bottom
|
|
132
|
-
* impossible for every marker as soon as `paddingPx` exceeded
|
|
133
|
-
* `verticalGapPx` (4 vs 4 by default) — and at `paddingPx: 10` would hide
|
|
134
|
-
* every label on the map.
|
|
135
|
-
*/
|
|
136
|
-
private collides;
|
|
137
|
-
/** Write phase: only touches the DOM for markers whose decision actually changed. */
|
|
138
|
-
private applyDecisions;
|
|
139
|
-
}
|
|
140
|
-
//# sourceMappingURL=markerLayoutController.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"markerLayoutController.d.ts","sourceRoot":"","sources":["../../../src/controllers/markerLayoutController.ts"],"names":[],"mappings":"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"}
|