adds multi trail support for maplibre

This commit is contained in:
Christian Beutel
2024-11-29 18:36:33 +01:00
parent c91f2afcc5
commit 390a7b52ee
16 changed files with 621 additions and 221 deletions

View File

@@ -6,22 +6,18 @@
import ListCard from "$lib/components/list/list_card.svelte";
import ListPanel from "$lib/components/list/list_panel.svelte";
import ListShareModal from "$lib/components/list/list_share_modal.svelte";
import MapWithElevationMultiple from "$lib/components/trail/map_with_elevation_multiple.svelte";
import MapWithElevationMaplibre from "$lib/components/trail/map_with_elevation_maplibre.svelte";
import TrailInfoPanel from "$lib/components/trail/trail_info_panel.svelte";
import TrailList from "$lib/components/trail/trail_list.svelte";
import { List } from "$lib/models/list";
import type { Trail } from "$lib/models/trail";
import {
list,
lists,
lists_delete,
lists_index,
lists_index
} from "$lib/stores/list_store";
import { fetchGPX } from "$lib/stores/trail_store";
import "$lib/vendor/leaflet-elevation/src/index.css";
import type { Map } from "leaflet";
import "leaflet.awesome-markers/dist/leaflet.awesome-markers.css";
import "leaflet/dist/leaflet.css";
import * as M from "maplibre-gl";
import { onMount, tick } from "svelte";
import { _ } from "svelte-i18n";
@@ -29,14 +25,16 @@
let openConfirmModal: () => void;
let openShareModal: () => void;
let map: Map;
let mapWithElevationMultiple: MapWithElevationMultiple;
let map: M.Map;
let mapWithElevation: MapWithElevationMaplibre;
let markers: any[];
let showMap: boolean = true;
let selectedList: List | null = null;
let selectedTrail: Trail | null = null;
let activeTrailIndex: number = -1;
onMount(() => {
if ($page.url.searchParams.get("list")) {
const listToFocus = $lists.find(
@@ -86,32 +84,32 @@
selectedList = item;
}
function back() {
async function back() {
if (selectedTrail) {
mapWithElevation.unFocusTrail(selectedTrail);
selectedTrail = null;
mapWithElevationMultiple.resetSelection();
} else if (selectedList) {
selectedList = null;
map.flyTo([0, 0], 4, {
duration: 0.25,
easeLinearity: 0.25,
noMoveStart: true,
map.flyTo({
animate: true,
zoom: 1,
center: [0, 0],
});
}
}
function selectTrail(trail: Trail) {
selectedTrail = trail;
mapWithElevationMultiple.selectTrail(trail.id!);
mapWithElevation.focusTrail(trail);
window.scrollTo({ top: 0 });
}
function highlightTrail(trail: Trail) {
mapWithElevationMultiple.highlightTrail(trail.id!);
mapWithElevation.highlightTrail(trail.id!);
}
function unHighlightTrail(trail: Trail) {
mapWithElevationMultiple.unHighlightTrail(trail.id!);
mapWithElevation.unHighlightTrail(trail.id!);
}
</script>
@@ -170,17 +168,17 @@
</div>
</div>
<div id="trail-map" class="md:sticky md:top-[62px]" class:hidden={!showMap}>
<MapWithElevationMultiple
<MapWithElevationMaplibre
trails={selectedList?.expand?.trails ?? []}
bind:map
bind:this={mapWithElevationMultiple}
bind:this={mapWithElevation}
bind:markers
on:select={(e) => {
selectedTrail = e.detail
selectedTrail = e.detail;
}}
bindRoutePopup={false}
options={{ itinerary: true, flyToBounds: true }}
></MapWithElevationMultiple>
bind:activeTrail={activeTrailIndex}
showInfoPopup={true}
></MapWithElevationMaplibre>
</div>
<div class="min-w-0" class:hidden={showMap}>
<TrailList trails={selectedList?.expand?.trails ?? []}></TrailList>

View File

@@ -10,10 +10,16 @@
} from "$lib/components/base/search.svelte";
import TextField from "$lib/components/base/text_field.svelte";
import Textarea from "$lib/components/base/textarea.svelte";
import MapWithElevationMultiple from "$lib/components/trail/map_with_elevation_multiple.svelte";
import ConfirmModal from "$lib/components/confirm_modal.svelte";
import MapWithElevationMaplibre from "$lib/components/trail/map_with_elevation_maplibre.svelte";
import type { Trail } from "$lib/models/trail.js";
import { TrailShare } from "$lib/models/trail_share.js";
import { lists_create, lists_update } from "$lib/stores/list_store.js";
import { show_toast } from "$lib/stores/toast_store.js";
import {
trail_share_create,
trail_share_index,
} from "$lib/stores/trail_share_store.js";
import { trails_show } from "$lib/stores/trail_store";
import { getFileURL } from "$lib/util/file_util.js";
import {
@@ -21,21 +27,15 @@
formatElevation,
formatTimeHHMM,
} from "$lib/util/format_util";
import {
trail_share_create,
trail_share_index,
} from "$lib/stores/trail_share_store.js";
import { TrailShare } from "$lib/models/trail_share.js";
import ConfirmModal from "$lib/components/confirm_modal.svelte";
export let data;
let previewURL = data.previewUrl ?? "";
let searchDropdownItems: SearchItem[] = [];
let activeTrailIndex: number | null = null;
let activeTrailIndex: number = -1;
let map: MapWithElevationMultiple;
let map: MapWithElevationMaplibre;
let loading: boolean = false;
@@ -301,7 +301,9 @@
trail.difficulty ?? "?",
)}</span
>
<div class="grid grid-cols-2 mt-1 gap-x-4 gap-y-2 text-sm text-gray-500">
<div
class="grid grid-cols-2 mt-1 gap-x-4 gap-y-2 text-sm text-gray-500"
>
<span
><i class="fa fa-left-right mr-2"
></i>{formatDistance(trail.distance)}</span
@@ -368,12 +370,11 @@
>
</form>
<div id="trail-map" class="max-h-full">
<MapWithElevationMultiple
<MapWithElevationMaplibre
trails={$form.expand?.trails ?? []}
options={{ flyToBounds: true }}
bind:activeTrailIndex
bind:activeTrail={activeTrailIndex}
bind:this={map}
></MapWithElevationMultiple>
></MapWithElevationMaplibre>
</div>
</main>

View File

@@ -6,7 +6,7 @@
type SearchItem,
} from "$lib/components/base/search.svelte";
import EmptyStateSearch from "$lib/components/empty_states/empty_state_search.svelte";
import MapWithElevationMultiple from "$lib/components/trail/map_with_elevation_multiple.svelte";
import MapWithElevationMaplibre from "$lib/components/trail/map_with_elevation_maplibre.svelte";
import TrailCard from "$lib/components/trail/trail_card.svelte";
import TrailFilterPanel from "$lib/components/trail/trail_filter_panel.svelte";
import type { Settings } from "$lib/models/settings";
@@ -21,21 +21,13 @@
trails_search_bounding_box,
} from "$lib/stores/trail_store";
import { country_codes } from "$lib/util/country_code_util";
import "$lib/vendor/leaflet-elevation/src/index.css";
import type {
GPX,
LatLng,
LatLngBoundsExpression,
Map,
Marker,
} from "leaflet";
import "leaflet.awesome-markers/dist/leaflet.awesome-markers.css";
import "leaflet/dist/leaflet.css";
import * as M from "maplibre-gl";
import { onMount } from "svelte";
import { _ } from "svelte-i18n";
import { slide } from "svelte/transition";
let map: Map;
let mapWithElevation: MapWithElevationMultiple;
let map: M.Map;
let mapWithElevation: MapWithElevationMaplibre;
let searchDropdownItems: SearchItem[] = [];
let showFilter: boolean = false;
@@ -45,6 +37,8 @@
const maxBoundingBox: TrailBoundingBox = $page.data.boundingBox;
const settings: Settings = $page.data.settings;
const MIN_ZOOM = 6;
onMount(async () => {});
async function search(q: string) {
@@ -93,23 +87,25 @@
}
function handleSearchClick(item: SearchItem) {
map.setView([item.value._geo.lat, item.value._geo.lng], 14);
map.setCenter([item.value._geo.lng, item.value._geo.lat]);
map.setZoom(14);
}
async function searchTrails(northEast: LatLng, southWest: LatLng) {
async function searchTrails(northEast: M.LngLat, southWest: M.LngLat) {
const changes = await trails_search_bounding_box(
northEast,
southWest,
filter,
map.getZoom() > MIN_ZOOM
);
}
function handleTrailCardMouseEnter(trail: Trail) {
mapWithElevation.openPopup(trail.id!)
mapWithElevation.togglePopup(trail.id!);
}
function handleTrailCardMouseLeave(trail: Trail) {
mapWithElevation.closePopup(trail.id!)
mapWithElevation.togglePopup(trail.id!);
}
async function handleFilterUpdate(filter: TrailFilter) {
@@ -136,29 +132,37 @@
$page.url.searchParams.has("br_lat") &&
$page.url.searchParams.has("br_lon")
) {
const boundingBox: LatLngBoundsExpression = [
[parseFloat($page.url.searchParams.get("br_lat")!), parseFloat($page.url.searchParams.get("tl_lon")!)],
[parseFloat($page.url.searchParams.get("tl_lat")!), parseFloat($page.url.searchParams.get("br_lon")!)],
const boundingBox: M.LngLatBoundsLike = [
[
parseFloat($page.url.searchParams.get("br_lon")!),
parseFloat($page.url.searchParams.get("tl_lat")!),
],
[
parseFloat($page.url.searchParams.get("tl_lon")!),
parseFloat($page.url.searchParams.get("br_lat")!),
],
];
map.fitBounds(boundingBox);
map.fitBounds(boundingBox, { animate: false });
} else if (settings && settings.mapFocus == "trails") {
const boundingBox: LatLngBoundsExpression = [
[maxBoundingBox.max_lat, maxBoundingBox.min_lon],
[maxBoundingBox.min_lat, maxBoundingBox.max_lon],
const boundingBox: M.LngLatBoundsLike = [
[maxBoundingBox.min_lon, maxBoundingBox.max_lat],
[maxBoundingBox.max_lon, maxBoundingBox.min_lat],
];
map.fitBounds(boundingBox);
map.fitBounds(boundingBox, { animate: false, padding: 32 });
} else if (
settings &&
settings.mapFocus == "location" &&
settings.location
) {
map.setView([settings.location.lat, settings.location.lon], 12);
map.setCenter([settings.location.lon, settings.location.lat]);
map.setZoom(12);
} else {
navigator.geolocation.getCurrentPosition(
(position) => {
const lat = position.coords.latitude;
const lon = position.coords.longitude;
map.setView([lat, lon], 13);
map.setCenter([lat, lon]);
map.setZoom(12);
},
(error) => {
console.error("Error getting user location:", error);
@@ -235,14 +239,17 @@
id="trail-map"
class:hidden={!showMap && browser && window.innerWidth < 768}
>
<MapWithElevationMultiple
<MapWithElevationMaplibre
on:moveend={handleMapMove}
on:init={handleMapInit}
trails={$trails}
options={{ flyToBounds: false }}
showElevation={false}
showInfoPopup={true}
activeTrail={-1}
minZoom={MIN_ZOOM}
bind:map
bind:this={mapWithElevation}
></MapWithElevationMultiple>
></MapWithElevationMaplibre>
</div>
</main>

View File

@@ -18,7 +18,7 @@
<main class="grid grid-cols-1 md:grid-cols-[458px_1fr] gap-x-1 gap-y-4">
<TrailInfoPanel trail={$trail} {markers}></TrailInfoPanel>
<div id="trail-details" class="sticky top-[62px]">
<MapWithElevationMaplibre trail={$trail} bind:markers></MapWithElevationMaplibre>
<MapWithElevationMaplibre trails={[$trail]} bind:markers></MapWithElevationMaplibre>
</div>
</main>

View File

@@ -1,8 +0,0 @@
<script>
import MapWithElevationMaplibre from "$lib/components/trail/map_with_elevation_maplibre.svelte";
import { onMount } from "svelte";
export let data;
</script>
<MapWithElevationMaplibre trail={data.trail}></MapWithElevationMaplibre>

View File

@@ -1,9 +0,0 @@
import type { Trail } from "$lib/models/trail";
import { trails_show } from "$lib/stores/trail_store";
export const load = async ({ params, fetch }) => {
const t: Trail = await trails_show("yesm2tqc6jok8jq", true, fetch)
return { trail: t }
};

View File

@@ -921,7 +921,7 @@
</div>
{/if}
<MapWithElevationMaplibre
trail={$form}
trails={[$form]}
drawing={drawingActive}
bind:map
on:click={(e) => handleMapClick(e.detail)}