fix(markers): stop wiping MapLibre's marker class (markers stacked in flow)

Re-setting el.className each render dropped the maplibregl-marker class
(position:absolute), so live markers fell into document flow and stacked
+32px each — vehicles drifted south, worse when zoomed out, dragging their
plate labels with them. Use classList (preserve maplibregl-marker) and wrap
pin+plate in a .veh-inner positioning context so a class change can't reflow.

Verified: every marker now projects to dX=0,dY=0 on its coordinate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
kianiadee 2026-06-05 22:45:41 +03:00
parent 3d420fa82e
commit 50163536e3

View file

@ -176,7 +176,12 @@
}
/* ── Live vehicle DOM marker (locked look) ─────────────────────────── */
.veh-marker { position: relative; cursor: pointer; will-change: transform; }
/* NOTE: never set position on .veh-marker — MapLibre's own .maplibregl-marker
class supplies position:absolute and drives placement. The plate's
positioning context is the inner wrapper below, so a class change can't
reflow the markers. */
.veh-marker { cursor: pointer; will-change: transform; }
.veh-inner { position: relative; width: 32px; height: 32px; }
.veh-pin {
width: 32px; height: 32px; border-radius: 50%;
background: var(--c, var(--parked));
@ -507,7 +512,7 @@ function upsertLiveMarker(p, coords, feature) {
if (!m) {
const el = document.createElement('div');
el.className = 'veh-marker';
el.innerHTML = `<div class="veh-pin"><span class="glyph"></span></div><div class="veh-plate"></div>`;
el.innerHTML = `<div class="veh-inner"><div class="veh-pin"><span class="glyph"></span></div><div class="veh-plate"></div></div>`;
el.addEventListener('mouseenter', () => { cancelPopupClose(); openPopupImei = p.imei; const f = currentLiveFeature(p.imei); if (f) showLivePopup(f); });
el.addEventListener('mouseleave', () => { if (!popupStuck) schedulePopupClose(); });
el.addEventListener('click', e => {
@ -520,9 +525,13 @@ function upsertLiveMarker(p, coords, feature) {
} else {
m.setLngLat(coords);
}
// Style the (possibly reused) element to current state
// Style the (possibly reused) element to current state. Use classList so we
// never wipe MapLibre's own `maplibregl-marker` class (doing so dropped
// position:absolute and made markers stack in document flow — FIX).
const el = m.getElement();
el.className = 'veh-marker ' + state;
el.classList.add('veh-marker');
el.classList.remove('active', 'parked', 'offline');
el.classList.add(state);
const pin = el.querySelector('.veh-pin');
pin.style.setProperty('--c', color);
const glyph = el.querySelector('.glyph');