fix: styles and add zooming into location

This commit is contained in:
2025-10-03 15:27:02 +02:00
parent b82141eb75
commit 00da815d52
4 changed files with 118 additions and 130 deletions

View File

@@ -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">

View File

@@ -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
});