fix: styles and add zooming into location
This commit is contained in:
@@ -1,7 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { MapLibre } from 'svelte-maplibre';
|
||||
import { MapLibre, Marker } from 'svelte-maplibre';
|
||||
import type { StyleSpecification } from 'svelte-maplibre';
|
||||
import { coordinates, getMapCenter, getMapZoom } from '$lib/stores/location';
|
||||
import {
|
||||
coordinates,
|
||||
getMapCenter,
|
||||
getMapZoom,
|
||||
shouldZoomToLocation,
|
||||
locationActions
|
||||
} from '$lib/stores/location';
|
||||
import LocationButton from './LocationButton.svelte';
|
||||
|
||||
interface Props {
|
||||
@@ -41,16 +47,46 @@
|
||||
|
||||
// Reactive center and zoom based on location or props
|
||||
const mapCenter = $derived(
|
||||
$coordinates && autoCenter
|
||||
$coordinates && (autoCenter || $shouldZoomToLocation)
|
||||
? ([$coordinates.longitude, $coordinates.latitude] as [number, number])
|
||||
: center || $getMapCenter
|
||||
);
|
||||
|
||||
const mapZoom = $derived($coordinates && autoCenter ? zoom || $getMapZoom : zoom || 13);
|
||||
const mapZoom = $derived(() => {
|
||||
if ($shouldZoomToLocation && $coordinates) {
|
||||
// Force zoom to calculated level when location button is clicked
|
||||
return $getMapZoom;
|
||||
}
|
||||
if ($coordinates && autoCenter) {
|
||||
return $getMapZoom;
|
||||
}
|
||||
return zoom || 13;
|
||||
});
|
||||
|
||||
// Effect to clear zoom trigger after it's been used
|
||||
$effect(() => {
|
||||
if ($shouldZoomToLocation) {
|
||||
// Use a timeout to ensure the map has updated before clearing the trigger
|
||||
setTimeout(() => {
|
||||
locationActions.clearZoomTrigger();
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="map-container {className}">
|
||||
<MapLibre {style} center={mapCenter} zoom={mapZoom} />
|
||||
<MapLibre {style} center={mapCenter} zoom={mapZoom()}>
|
||||
{#if $coordinates}
|
||||
<Marker lngLat={[$coordinates.longitude, $coordinates.latitude]}>
|
||||
<div class="location-marker">
|
||||
<div class="marker-pulse"></div>
|
||||
<div class="marker-outer">
|
||||
<div class="marker-inner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</Marker>
|
||||
{/if}
|
||||
</MapLibre>
|
||||
|
||||
{#if showLocationButton}
|
||||
<div class="location-controls">
|
||||
|
||||
@@ -12,6 +12,7 @@ interface LocationState {
|
||||
error: LocationError | null;
|
||||
isWatching: boolean;
|
||||
lastUpdated: Date | null;
|
||||
shouldZoomToLocation: boolean;
|
||||
}
|
||||
|
||||
const initialState: LocationState = {
|
||||
@@ -19,7 +20,8 @@ const initialState: LocationState = {
|
||||
status: 'idle',
|
||||
error: null,
|
||||
isWatching: false,
|
||||
lastUpdated: null
|
||||
lastUpdated: null,
|
||||
shouldZoomToLocation: false
|
||||
};
|
||||
|
||||
// Main location store
|
||||
@@ -37,6 +39,10 @@ export const hasLocationAccess = derived(
|
||||
locationStore,
|
||||
($location) => $location.coordinates !== null
|
||||
);
|
||||
export const shouldZoomToLocation = derived(
|
||||
locationStore,
|
||||
($location) => $location.shouldZoomToLocation
|
||||
);
|
||||
|
||||
// Location actions
|
||||
export const locationActions = {
|
||||
@@ -58,7 +64,8 @@ export const locationActions = {
|
||||
coordinates,
|
||||
status: 'success',
|
||||
error: null,
|
||||
lastUpdated: new Date()
|
||||
lastUpdated: new Date(),
|
||||
shouldZoomToLocation: true
|
||||
}));
|
||||
|
||||
return coordinates;
|
||||
@@ -169,6 +176,16 @@ export const locationActions = {
|
||||
|
||||
const ageInMinutes = (Date.now() - currentState.lastUpdated.getTime()) / (1000 * 60);
|
||||
return ageInMinutes > maxAgeMinutes;
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear the zoom trigger flag
|
||||
*/
|
||||
clearZoomTrigger(): void {
|
||||
locationStore.update((state) => ({
|
||||
...state,
|
||||
shouldZoomToLocation: false
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -182,14 +199,17 @@ export const getMapCenter = derived(coordinates, ($coordinates) => {
|
||||
});
|
||||
|
||||
// Utility function to get appropriate zoom level based on accuracy
|
||||
export const getMapZoom = derived(coordinates, ($coordinates) => {
|
||||
export const getMapZoom = derived([coordinates, shouldZoomToLocation], ([$coordinates, $shouldZoom]) => {
|
||||
if ($coordinates?.accuracy) {
|
||||
// More aggressive zoom levels when location button is clicked
|
||||
const baseZoom = $shouldZoom ? 2 : 0; // Add 2 zoom levels when triggered by button
|
||||
|
||||
// Adjust zoom based on accuracy (lower accuracy = lower zoom)
|
||||
if ($coordinates.accuracy < 10) return 18; // Very accurate
|
||||
if ($coordinates.accuracy < 50) return 16; // Good accuracy
|
||||
if ($coordinates.accuracy < 100) return 14; // Moderate accuracy
|
||||
if ($coordinates.accuracy < 500) return 12; // Low accuracy
|
||||
return 10; // Very low accuracy
|
||||
if ($coordinates.accuracy < 10) return Math.min(20, 18 + baseZoom); // Very accurate
|
||||
if ($coordinates.accuracy < 50) return Math.min(19, 16 + baseZoom); // Good accuracy
|
||||
if ($coordinates.accuracy < 100) return Math.min(18, 14 + baseZoom); // Moderate accuracy
|
||||
if ($coordinates.accuracy < 500) return Math.min(16, 12 + baseZoom); // Low accuracy
|
||||
return Math.min(15, 10 + baseZoom); // Very low accuracy
|
||||
}
|
||||
return 13; // Default zoom level
|
||||
return $shouldZoom ? 16 : 13; // More aggressive default when triggered by button
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user