Skip to content

Commit 6d1330c

Browse files
committed
widgets: map: add wp number tooltip for low zoom levels
Signed-off-by: Arturo Manzoli <arturomanzoli@gmail.com>
1 parent 27a03de commit 6d1330c

1 file changed

Lines changed: 200 additions & 56 deletions

File tree

src/components/widgets/Map.vue

Lines changed: 200 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ const showButtons = computed(() => isMouseOver.value || downloadMenuOpen.value)
252252
const mapReady = ref(false)
253253
const mapWaypoints = ref<Waypoint[]>([])
254254
const reachedWaypoints = shallowRef<Record<number, L.Marker>>({})
255+
const persistentTooltipSeq = ref<number | undefined>(undefined)
255256
const contextMenuRef = ref()
256257
const isDragging = ref(false)
257258
const isPinching = ref(false)
@@ -394,24 +395,102 @@ const applyWaypointMarkerStyle = (seq: number): void => {
394395
})
395396
)
396397
397-
// Updates the tooltip class for reached/current waypoints and visibility based on size
398-
const tooltip = marker.getTooltip()
399-
if (tooltip) {
400-
if (markerSize === 'xs' || markerSize === 'sm') {
401-
tooltip.setOpacity(0)
398+
// Updates the tooltip for reached/current waypoints and visibility based on size
399+
const isPersistent = persistentTooltipSeq.value === seq
400+
marker.off('mouseover')
401+
marker.off('mouseout')
402+
marker.unbindTooltip()
403+
404+
if (markerSize === 'xs' || markerSize === 'sm') {
405+
if (isPersistent) {
406+
const permanentTooltip = L.tooltip({
407+
content: seq.toString(),
408+
permanent: true,
409+
direction: 'top',
410+
className: 'waypoint-hover-tooltip',
411+
opacity: 1,
412+
interactive: false,
413+
})
414+
marker.bindTooltip(permanentTooltip)
415+
marker.openTooltip()
402416
} else {
403-
tooltip.setOpacity(1)
417+
const hoverTooltip = L.tooltip({
418+
content: seq.toString(),
419+
permanent: false,
420+
direction: 'top',
421+
className: 'waypoint-hover-tooltip',
422+
interactive: false,
423+
})
424+
marker.bindTooltip(hoverTooltip)
425+
marker.on('mouseover', () => {
426+
marker.openTooltip()
427+
})
428+
marker.on('mouseout', () => {
429+
marker.closeTooltip()
430+
})
404431
}
405432
406-
const tooltipElement = tooltip.getElement()
407-
if (tooltipElement) {
408-
tooltipElement.classList.remove('waypoint-tooltip--reached', 'waypoint-tooltip--current-waypoint')
409-
if (isReached) {
410-
tooltipElement.classList.add('waypoint-tooltip--reached')
411-
} else if (isCurrent) {
412-
tooltipElement.classList.add('waypoint-tooltip--current-waypoint')
433+
marker.off('click')
434+
marker.on('click', (event: L.LeafletMouseEvent) => {
435+
L.DomEvent.stopPropagation(event)
436+
persistentTooltipSeq.value = persistentTooltipSeq.value === seq ? undefined : seq
437+
refreshReachedWaypointMarkerStyles()
438+
if (persistentTooltipSeq.value === seq) {
439+
nextTick(() => {
440+
const persistentMarker = reachedWaypoints.value[seq]
441+
if (persistentMarker) {
442+
const tip = persistentMarker.getTooltip()
443+
if (tip) {
444+
persistentMarker.openTooltip()
445+
const tipEl = tip.getElement()
446+
if (tipEl) {
447+
tipEl.style.display = 'block'
448+
tipEl.style.opacity = '1'
449+
}
450+
}
451+
}
452+
})
413453
}
454+
})
455+
} else {
456+
let tooltipClass = 'waypoint-tooltip'
457+
if (isReached) {
458+
tooltipClass = 'waypoint-tooltip waypoint-tooltip--reached'
459+
} else if (isCurrent) {
460+
tooltipClass = 'waypoint-tooltip waypoint-tooltip--current-waypoint'
414461
}
462+
463+
const permanentTooltip = L.tooltip({
464+
content: seq.toString(),
465+
permanent: true,
466+
direction: 'center',
467+
className: tooltipClass,
468+
opacity: 1,
469+
})
470+
marker.bindTooltip(permanentTooltip)
471+
472+
marker.off('click')
473+
marker.on('click', (event: L.LeafletMouseEvent) => {
474+
L.DomEvent.stopPropagation(event)
475+
persistentTooltipSeq.value = persistentTooltipSeq.value === seq ? undefined : seq
476+
refreshReachedWaypointMarkerStyles()
477+
if (persistentTooltipSeq.value === seq) {
478+
nextTick(() => {
479+
const persistentMarker = reachedWaypoints.value[seq]
480+
if (persistentMarker) {
481+
const tip = persistentMarker.getTooltip()
482+
if (tip) {
483+
persistentMarker.openTooltip()
484+
const tipEl = tip.getElement()
485+
if (tipEl) {
486+
tipEl.style.display = 'block'
487+
tipEl.style.opacity = '1'
488+
}
489+
}
490+
}
491+
})
492+
}
493+
})
415494
}
416495
}
417496
@@ -631,15 +710,66 @@ onMounted(async () => {
631710
632711
map.value.on('click', (event: LeafletMouseEvent) => {
633712
clickedLocation.value = [event.latlng.lat, event.latlng.lng]
713+
if (persistentTooltipSeq.value !== undefined) {
714+
persistentTooltipSeq.value = undefined
715+
refreshReachedWaypointMarkerStyles()
716+
}
717+
})
718+
719+
// Keep persistent tooltips visible during map drag
720+
let tooltipReopenTimeout: ReturnType<typeof setTimeout> | undefined
721+
const keepPersistentTooltipVisible = (): void => {
722+
if (persistentTooltipSeq.value !== undefined) {
723+
const marker = reachedWaypoints.value[persistentTooltipSeq.value]
724+
if (marker) {
725+
const tooltip = marker.getTooltip()
726+
if (tooltip) {
727+
marker.openTooltip()
728+
const tooltipElement = tooltip.getElement()
729+
if (tooltipElement) {
730+
tooltipElement.style.display = 'block'
731+
tooltipElement.style.opacity = '1'
732+
}
733+
}
734+
}
735+
}
736+
}
737+
738+
map.value.on('movestart', () => {
739+
keepPersistentTooltipVisible()
740+
})
741+
742+
map.value.on('move', () => {
743+
if (persistentTooltipSeq.value !== undefined) {
744+
if (tooltipReopenTimeout) {
745+
clearTimeout(tooltipReopenTimeout)
746+
}
747+
tooltipReopenTimeout = setTimeout(() => {
748+
keepPersistentTooltipVisible()
749+
}, 50)
750+
}
634751
})
635752
636753
// Update center value after panning
637754
map.value.on('moveend', () => {
755+
if (tooltipReopenTimeout) {
756+
clearTimeout(tooltipReopenTimeout)
757+
tooltipReopenTimeout = undefined
758+
}
638759
if (map.value === undefined) return
639760
let { lat, lng } = map.value.getCenter()
640761
if (lat && lng) {
641762
mapCenter.value = [lat, lng]
642763
}
764+
if (persistentTooltipSeq.value !== undefined) {
765+
const marker = reachedWaypoints.value[persistentTooltipSeq.value]
766+
if (marker) {
767+
const tooltip = marker.getTooltip()
768+
if (tooltip) {
769+
marker.openTooltip()
770+
}
771+
}
772+
}
643773
})
644774
645775
// Builds map layers offline content controls
@@ -686,6 +816,7 @@ onMounted(async () => {
686816
687817
map.value.on('dragstart', () => {
688818
isDragging.value = true
819+
keepPersistentTooltipVisible()
689820
})
690821
691822
map.value.on('dragend', () => {
@@ -1236,38 +1367,60 @@ watch(
12361367
reachedWaypoints.value[seq] = marker
12371368
12381369
const markerSizeForTooltip = getMarkerSizeFromZoom(zoom.value)
1239-
const markerTooltip = L.tooltip({
1240-
content: seq.toString(),
1241-
permanent: true,
1242-
direction: 'center',
1243-
className: isReached
1244-
? 'waypoint-tooltip waypoint-tooltip--reached'
1245-
: isCurrent
1246-
? 'waypoint-tooltip waypoint-tooltip--current-waypoint'
1247-
: 'waypoint-tooltip',
1248-
opacity: markerSizeForTooltip === 'md' ? 1 : 0,
1370+
1371+
marker.off('click')
1372+
marker.on('click', (event: L.LeafletMouseEvent) => {
1373+
L.DomEvent.stopPropagation(event)
1374+
persistentTooltipSeq.value = persistentTooltipSeq.value === seq ? undefined : seq
1375+
refreshReachedWaypointMarkerStyles()
12491376
})
12501377
1251-
marker.bindTooltip(markerTooltip)
12521378
marker.on('contextmenu', (e: L.LeafletMouseEvent) => {
12531379
L.DomEvent.stopPropagation(e)
12541380
e.originalEvent.stopPropagation()
12551381
e.originalEvent.preventDefault()
12561382
openContextMenuAt(e.originalEvent, seq)
12571383
})
1384+
1385+
if (markerSizeForTooltip === 'xs' || markerSizeForTooltip === 'sm') {
1386+
const hoverTooltip = L.tooltip({
1387+
content: seq.toString(),
1388+
permanent: false,
1389+
direction: 'top',
1390+
className: 'waypoint-hover-tooltip',
1391+
interactive: false,
1392+
})
1393+
marker.bindTooltip(hoverTooltip)
1394+
marker.on('mouseover', () => {
1395+
if (persistentTooltipSeq.value !== seq) {
1396+
marker.openTooltip()
1397+
}
1398+
})
1399+
marker.on('mouseout', () => {
1400+
if (persistentTooltipSeq.value !== seq) {
1401+
marker.closeTooltip()
1402+
}
1403+
})
1404+
} else {
1405+
let tooltipClass = 'waypoint-tooltip'
1406+
if (isReached) {
1407+
tooltipClass = 'waypoint-tooltip waypoint-tooltip--reached'
1408+
} else if (isCurrent) {
1409+
tooltipClass = 'waypoint-tooltip waypoint-tooltip--current-waypoint'
1410+
}
1411+
const permanentTooltip = L.tooltip({
1412+
content: seq.toString(),
1413+
permanent: true,
1414+
direction: 'center',
1415+
className: tooltipClass,
1416+
opacity: 1,
1417+
})
1418+
marker.bindTooltip(permanentTooltip)
1419+
}
1420+
12581421
map.value?.addLayer(marker)
12591422
} else {
12601423
marker.setLatLng(waypoint.coordinates as LatLngTuple)
1261-
const markerSizeForUpdate = getMarkerSizeFromZoom(zoom.value)
1262-
const tooltip = marker.getTooltip()
1263-
if (tooltip) {
1264-
if (markerSizeForUpdate === 'xs' || markerSizeForUpdate === 'sm') {
1265-
tooltip.setOpacity(0)
1266-
} else {
1267-
tooltip.setContent(seq.toString())
1268-
tooltip.setOpacity(1)
1269-
}
1270-
}
12711424
applyWaypointMarkerStyle(seq)
12721425
}
12731426
})
@@ -1277,28 +1430,7 @@ watch(
12771430
12781431
// Keep an eye on the current mission status and update the waypoint markers accordingly
12791432
watch([vehicleStore.currentMissionSeq, currentVehicleWpIndex, getReachedWaypointIndices, currentMapWpIndex], () => {
1280-
Object.entries(reachedWaypoints.value).forEach(([seqStr, marker]) => {
1281-
const seq = Number(seqStr)
1282-
const idx = seq - 1
1283-
const isCurrent = currentMapWpIndex.value >= 0 && idx === currentMapWpIndex.value
1284-
const isReached = getReachedWaypointIndices.value.has(seq)
1285-
1286-
applyWaypointMarkerStyle(seq)
1287-
1288-
const tooltip = marker.getTooltip()
1289-
if (tooltip) {
1290-
const tooltipElement = tooltip.getElement()
1291-
if (tooltipElement) {
1292-
tooltipElement.classList.remove('waypoint-tooltip--reached', 'waypoint-tooltip--current-waypoint')
1293-
if (isReached) {
1294-
tooltipElement.classList.add('waypoint-tooltip--reached')
1295-
} else if (isCurrent) {
1296-
tooltipElement.classList.add('waypoint-tooltip--current-waypoint')
1297-
}
1298-
}
1299-
tooltip.update()
1300-
}
1301-
})
1433+
refreshReachedWaypointMarkerStyles()
13021434
})
13031435
13041436
// Create polyline for the vehicle path
@@ -1900,6 +2032,18 @@ watch(
19002032
box-shadow: 0 0 6px rgba(255, 255, 255, 0.2);
19012033
}
19022034
2035+
:deep(.waypoint-hover-tooltip) {
2036+
background-color: #1e498f;
2037+
color: white;
2038+
border: 1px solid rgba(255, 255, 255, 0.3);
2039+
border-radius: 8px;
2040+
padding: 4px 8px;
2041+
font-size: 12px;
2042+
font-weight: bold;
2043+
margin-top: -12px;
2044+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
2045+
}
2046+
19032047
:global(.marker-icon) {
19042048
background-color: #1e498f;
19052049
border: 1px solid #ffffff55;

0 commit comments

Comments
 (0)