Map: pin current view before 'Search this area' to defeat camera stop-revert
The native MapLibre camera re-applies its last setCamera() stop on the search re-render (confirmed via trace: revert to prior target with userInteraction=false). Track the live viewport and, before searching the current area, setCamera() to the current center (0ms) so the re-applied stop is a no-op instead of a jump-back. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
a4150555ae
commit
7321453337
1 changed files with 20 additions and 9 deletions
|
|
@ -59,6 +59,11 @@ export function MapScreen() {
|
|||
// We position the camera exactly once, then never auto-recenter — otherwise
|
||||
// re-renders (from searching) would snap the map back and fight the user's pan.
|
||||
const positioned = useRef(false);
|
||||
// The live viewport, tracked from region changes. MapLibre's native camera
|
||||
// re-applies its last setCamera() stop on any re-render, so before a search we
|
||||
// overwrite that stop with the current view (zero-duration) — otherwise the
|
||||
// results re-render snaps the map back to the previous programmatic target.
|
||||
const viewRef = useRef<{ center: [number, number]; zoom: number } | null>(null);
|
||||
// The native UserLocation dot has its own GPS feed — capture it so "My
|
||||
// location" works even when expo-location can't get a fix (e.g. indoors).
|
||||
const nativeFix = useRef<Coords | null>(null);
|
||||
|
|
@ -109,15 +114,16 @@ export function MapScreen() {
|
|||
const searchThisArea = async () => {
|
||||
try {
|
||||
const center = await mapRef.current?.getCenter?.(); // [lng, lat]
|
||||
console.log('[CAM] searchThisArea getCenter=', JSON.stringify(center));
|
||||
if (center && center.length === 2) {
|
||||
// Commit the current view as the camera's stop so the results re-render
|
||||
// doesn't revert to the last programmatic (e.g. "My location") target.
|
||||
cameraRef.current?.setCamera?.({ centerCoordinate: center, animationDuration: 0 });
|
||||
await searchAt({ latitude: center[1], longitude: center[0] }, 'this area');
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('[CAM] getCenter threw', String(err));
|
||||
} catch {
|
||||
/* fall through */
|
||||
}
|
||||
console.log('[CAM] searchThisArea FALLBACK coords=', JSON.stringify(coords));
|
||||
if (coords) await searchAt(coords, 'this area');
|
||||
};
|
||||
|
||||
|
|
@ -212,14 +218,19 @@ export function MapScreen() {
|
|||
console.log('[CAM] onDidFinishLoadingMap (mapReady already', mapReady, ')');
|
||||
setMapReady(true);
|
||||
}}
|
||||
onRegionDidChange={(f: any) =>
|
||||
onRegionDidChange={(f: any) => {
|
||||
const c = f?.geometry?.coordinates;
|
||||
const z = f?.properties?.zoomLevel;
|
||||
if (Array.isArray(c) && c.length === 2) {
|
||||
viewRef.current = { center: [c[0], c[1]], zoom: typeof z === 'number' ? z : 14 };
|
||||
}
|
||||
console.log(
|
||||
'[CAM] regionDidChange center=',
|
||||
JSON.stringify(f?.geometry?.coordinates),
|
||||
'userInteraction=',
|
||||
JSON.stringify(c),
|
||||
'ui=',
|
||||
f?.properties?.isUserInteraction,
|
||||
)
|
||||
}
|
||||
);
|
||||
}}
|
||||
>
|
||||
{cameraEl}
|
||||
{userLocationEl}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue