feat(map): show overlay station label on hover, single popup
Switch the Shell layer from click→popup to hover: mousemove shows one reused popup that follows whichever station is under the cursor, mouseleave clears it — so only ever one label is visible. No click needed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
1532ef6ae0
commit
18501f00d3
1 changed files with 10 additions and 5 deletions
15
index.html
15
index.html
|
|
@ -635,6 +635,7 @@ const OVERLAYS = [
|
||||||
iconSvg: SHELL_ICON_SVG, nameKey: 'name', defaultOn: false },
|
iconSvg: SHELL_ICON_SVG, nameKey: 'name', defaultOn: false },
|
||||||
// future layers: add { id, label, url, iconSvg, nameKey, defaultOn } here.
|
// future layers: add { id, label, url, iconSvg, nameKey, defaultOn } here.
|
||||||
];
|
];
|
||||||
|
let overlayPopup = null; // single reused hover popup for overlay points (only one ever shown)
|
||||||
|
|
||||||
function registerOverlayIcon(def) {
|
function registerOverlayIcon(def) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
|
@ -667,14 +668,18 @@ async function addOverlay(def) {
|
||||||
'visibility': def.defaultOn ? 'visible' : 'none',
|
'visibility': def.defaultOn ? 'visible' : 'none',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
map.on('click', lyrId, e => {
|
// Hover (not click) shows a single label — one reused popup, so only ever
|
||||||
const p = (e.features[0] && e.features[0].properties) || {};
|
// one is visible; mousemove keeps it on whichever station is under the cursor.
|
||||||
popup.setLngLat(e.lngLat)
|
map.on('mouseenter', lyrId, () => { map.getCanvas().style.cursor = 'pointer'; });
|
||||||
|
map.on('mousemove', lyrId, e => {
|
||||||
|
const f = e.features[0]; if (!f) return;
|
||||||
|
const p = f.properties || {};
|
||||||
|
if (!overlayPopup) overlayPopup = new maplibregl.Popup({ closeButton: false, closeOnClick: false, offset: 12 });
|
||||||
|
overlayPopup.setLngLat(f.geometry.coordinates)
|
||||||
.setHTML(`<div class="ov-pop"><b>${escapeHtml(p[def.nameKey] || def.label)}</b><div class="ov-sub">${escapeHtml(p.brand || 'fuel station')}</div></div>`)
|
.setHTML(`<div class="ov-pop"><b>${escapeHtml(p[def.nameKey] || def.label)}</b><div class="ov-sub">${escapeHtml(p.brand || 'fuel station')}</div></div>`)
|
||||||
.addTo(map);
|
.addTo(map);
|
||||||
});
|
});
|
||||||
map.on('mouseenter', lyrId, () => { map.getCanvas().style.cursor = 'pointer'; });
|
map.on('mouseleave', lyrId, () => { map.getCanvas().style.cursor = ''; if (overlayPopup) overlayPopup.remove(); });
|
||||||
map.on('mouseleave', lyrId, () => { map.getCanvas().style.cursor = ''; });
|
|
||||||
}
|
}
|
||||||
buildLayersControl();
|
buildLayersControl();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue