Improved individual track selection behaviour.
Added track highlighting and automatic popup on selection.
This commit is contained in:
@@ -12,6 +12,10 @@ export default {
|
|||||||
tracks: {
|
tracks: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => []
|
||||||
|
},
|
||||||
|
selectedTrackIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
@@ -48,9 +52,12 @@ export default {
|
|||||||
if (!props.tracks || props.tracks.length === 0) return
|
if (!props.tracks || props.tracks.length === 0) return
|
||||||
|
|
||||||
const allBounds = []
|
const allBounds = []
|
||||||
|
let selectedTrackBounds = []
|
||||||
|
let selectedTrackPopupOpened = false
|
||||||
|
|
||||||
props.tracks.forEach((track, trackIndex) => {
|
props.tracks.forEach((track, trackIndex) => {
|
||||||
const color = getTrackColor(trackIndex)
|
const color = getTrackColor(trackIndex)
|
||||||
|
const isSelected = props.selectedTrackIndex === trackIndex
|
||||||
|
|
||||||
track.segments.forEach(segment => {
|
track.segments.forEach(segment => {
|
||||||
if (segment.points && segment.points.length > 0) {
|
if (segment.points && segment.points.length > 0) {
|
||||||
@@ -58,8 +65,9 @@ export default {
|
|||||||
|
|
||||||
const polyline = L.polyline(latLngs, {
|
const polyline = L.polyline(latLngs, {
|
||||||
color: color,
|
color: color,
|
||||||
weight: 3,
|
weight: isSelected ? 8 : 3,
|
||||||
opacity: 0.8
|
opacity: isSelected ? 1.0 : 0.6,
|
||||||
|
zIndexOffset: isSelected ? 1000 : 0
|
||||||
}).bindPopup(`
|
}).bindPopup(`
|
||||||
<div class="font-medium">${track.name}</div>
|
<div class="font-medium">${track.name}</div>
|
||||||
<div class="text-sm text-gray-600 mt-1">
|
<div class="text-sm text-gray-600 mt-1">
|
||||||
@@ -70,17 +78,54 @@ export default {
|
|||||||
`)
|
`)
|
||||||
|
|
||||||
polyline.addTo(map.value)
|
polyline.addTo(map.value)
|
||||||
trackLayers.value.push(polyline)
|
trackLayers.value.push({ polyline, trackIndex })
|
||||||
|
|
||||||
|
// Open popup for selected track (only for first segment)
|
||||||
|
if (isSelected && !selectedTrackPopupOpened) {
|
||||||
|
// Find the northernmost point (highest latitude)
|
||||||
|
const northernmostPoint = latLngs.reduce((north, current) =>
|
||||||
|
current[0] > north[0] ? current : north
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create popup at northernmost point
|
||||||
|
const popup = L.popup()
|
||||||
|
.setLatLng(northernmostPoint)
|
||||||
|
.setContent(`
|
||||||
|
<div class="font-medium">${track.name}</div>
|
||||||
|
<div class="text-sm text-gray-600 mt-1">
|
||||||
|
Distance: ${(track.stats?.distance / 1000 || 0).toFixed(1)} km<br>
|
||||||
|
Duration: ${Math.floor((track.stats?.duration || 0) / 3600)}:${Math.floor(((track.stats?.duration || 0) % 3600) / 60).toString().padStart(2, '0')}<br>
|
||||||
|
Avg Speed: ${track.stats?.avgSpeed || 0} km/h
|
||||||
|
</div>
|
||||||
|
`)
|
||||||
|
.openOn(map.value)
|
||||||
|
|
||||||
|
selectedTrackPopupOpened = true
|
||||||
|
}
|
||||||
|
|
||||||
// Add bounds for this segment
|
// Add bounds for this segment
|
||||||
allBounds.push(...latLngs)
|
allBounds.push(...latLngs)
|
||||||
|
|
||||||
|
// Collect bounds for selected track
|
||||||
|
if (isSelected) {
|
||||||
|
selectedTrackBounds.push(...latLngs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Fit map to show all tracks
|
// Focus on selected track if one is selected, otherwise show all tracks
|
||||||
if (allBounds.length > 0) {
|
if (selectedTrackBounds.length > 0) {
|
||||||
const group = new L.featureGroup(trackLayers.value)
|
const selectedGroup = L.latLngBounds(selectedTrackBounds)
|
||||||
|
|
||||||
|
// Add extra padding at the top to accommodate popup
|
||||||
|
// Popup is roughly 80-100px tall, so add more top padding
|
||||||
|
map.value.fitBounds(selectedGroup, {
|
||||||
|
paddingTopLeft: [50, 120], // Extra top padding for popup
|
||||||
|
paddingBottomRight: [50, 50]
|
||||||
|
})
|
||||||
|
} else if (allBounds.length > 0) {
|
||||||
|
const group = new L.featureGroup(trackLayers.value.map(item => item.polyline))
|
||||||
map.value.fitBounds(group.getBounds(), { padding: [20, 20] })
|
map.value.fitBounds(group.getBounds(), { padding: [20, 20] })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,8 +143,9 @@ export default {
|
|||||||
renderTracks()
|
renderTracks()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watch for track changes
|
// Watch for track changes and selection changes
|
||||||
watch(() => props.tracks, renderTracks, { deep: true })
|
watch(() => props.tracks, renderTracks, { deep: true })
|
||||||
|
watch(() => props.selectedTrackIndex, renderTracks)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initMap()
|
initMap()
|
||||||
|
|||||||
Reference in New Issue
Block a user