Compare commits

..

2 commits

Author SHA1 Message Date
david kiania
58525ec73d Merge: overlay hover label (single popup) 2026-06-08 21:53:09 +03:00
david kiania
18501f00d3 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>
2026-06-08 21:53:07 +03:00

View file

@ -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();
} }