mirror of
https://github.com/zvx-echo6/navi.git
synced 2026-05-20 22:54:42 +02:00
fix(map): resolve clicks to rendered label features
Click handler now queries rendered features at click point and uses the highest-priority labeled feature (POI > locality > region) as the place identifier. Previously, clicks went straight to coord-based reverse-geocode, causing 'Twin Falls' label clicks to resolve to whatever feature was nearest (e.g., a radio tower). Falls back to reverse-geocode when no labeled feature exists at the click point. Two-click selection model and hover affordance unchanged.
This commit is contained in:
parent
985221e8cd
commit
4fcc3d1af4
1 changed files with 51 additions and 23 deletions
|
|
@ -863,6 +863,13 @@ const MapView = forwardRef(function MapView(_, ref) {
|
||||||
const { lng, lat } = e.lngLat
|
const { lng, lat } = e.lngLat
|
||||||
const MARKER_RADIUS_PX = 14 // half of 28px preview marker
|
const MARKER_RADIUS_PX = 14 // half of 28px preview marker
|
||||||
|
|
||||||
|
// Query rendered features at click point (label/POI priority)
|
||||||
|
const labelLayers = ['pois', 'places_subplace', 'places_locality', 'places_region', 'places_country']
|
||||||
|
const features = map.queryRenderedFeatures(e.point, { layers: labelLayers })
|
||||||
|
|
||||||
|
// Find first feature with a name (respects layer order = priority)
|
||||||
|
const labelFeature = features.find(f => f.properties?.name)
|
||||||
|
|
||||||
// Set click marker
|
// Set click marker
|
||||||
store.setClickMarker({
|
store.setClickMarker({
|
||||||
lat,
|
lat,
|
||||||
|
|
@ -870,30 +877,51 @@ const MapView = forwardRef(function MapView(_, ref) {
|
||||||
circleRadiusPx: MARKER_RADIUS_PX,
|
circleRadiusPx: MARKER_RADIUS_PX,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Immediately set a "Dropped pin" placeholder
|
if (labelFeature) {
|
||||||
store.setSelectedPlace({
|
// Clicked a labeled feature — use its properties
|
||||||
lat,
|
const props = labelFeature.properties
|
||||||
lon: lng,
|
store.setSelectedPlace({
|
||||||
name: 'Dropped pin',
|
lat,
|
||||||
address: null,
|
lon: lng,
|
||||||
type: null,
|
name: props.name || 'Unknown',
|
||||||
source: 'map_click',
|
address: null,
|
||||||
matchCode: null,
|
type: props.kind_detail || props.kind || null,
|
||||||
raw: {},
|
source: 'basemap_label',
|
||||||
})
|
matchCode: null,
|
||||||
|
raw: {
|
||||||
|
wikidata: props.wikidata || null,
|
||||||
|
population: props.population || null,
|
||||||
|
kind: props.kind || null,
|
||||||
|
kind_detail: props.kind_detail || null,
|
||||||
|
elevation: props.elevation || null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// No labeled feature — fall back to reverse geocode
|
||||||
|
store.setSelectedPlace({
|
||||||
|
lat,
|
||||||
|
lon: lng,
|
||||||
|
name: 'Dropped pin',
|
||||||
|
address: null,
|
||||||
|
type: null,
|
||||||
|
source: 'map_click',
|
||||||
|
matchCode: null,
|
||||||
|
raw: {},
|
||||||
|
})
|
||||||
|
|
||||||
// Reverse geocode in background
|
// Reverse geocode in background
|
||||||
fetchReverse(lat, lng).then((place) => {
|
fetchReverse(lat, lng).then((place) => {
|
||||||
if (!place) return
|
if (!place) return
|
||||||
const current = useStore.getState().selectedPlace
|
const current = useStore.getState().selectedPlace
|
||||||
if (current && Math.abs(current.lat - lat) < 0.00001 && Math.abs(current.lon - lng) < 0.00001) {
|
if (current && Math.abs(current.lat - lat) < 0.00001 && Math.abs(current.lon - lng) < 0.00001) {
|
||||||
useStore.getState().setSelectedPlace({
|
useStore.getState().setSelectedPlace({
|
||||||
...place,
|
...place,
|
||||||
lat,
|
lat,
|
||||||
lon: lng,
|
lon: lng,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
map.on('load', () => {
|
map.on('load', () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue