map performance improvements
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
import type { Trail } from "$lib/models/trail";
|
import type { Trail } from "$lib/models/trail";
|
||||||
import type { Waypoint } from "$lib/models/waypoint";
|
import type { Waypoint } from "$lib/models/waypoint";
|
||||||
import { theme } from "$lib/stores/theme_store";
|
import { theme } from "$lib/stores/theme_store";
|
||||||
|
import { fetchGPX } from "$lib/stores/trail_store";
|
||||||
import { findStartAndEndPoints } from "$lib/util/geojson_util";
|
import { findStartAndEndPoints } from "$lib/util/geojson_util";
|
||||||
import { toGeoJson } from "$lib/util/gpx_util";
|
import { toGeoJson } from "$lib/util/gpx_util";
|
||||||
import {
|
import {
|
||||||
@@ -17,12 +18,8 @@
|
|||||||
import { FullscreenControl } from "$lib/vendor/maplibre-fullscreen/fullscreen-control";
|
import { FullscreenControl } from "$lib/vendor/maplibre-fullscreen/fullscreen-control";
|
||||||
import MaplibreGraticule from "$lib/vendor/maplibre-graticule/maplibre-graticule";
|
import MaplibreGraticule from "$lib/vendor/maplibre-graticule/maplibre-graticule";
|
||||||
import { StyleSwitcherControl } from "$lib/vendor/maplibre-style-switcher/style-switcher-control";
|
import { StyleSwitcherControl } from "$lib/vendor/maplibre-style-switcher/style-switcher-control";
|
||||||
import type {
|
import { T } from "@threlte/core";
|
||||||
Feature,
|
import type { Feature, FeatureCollection, GeoJSON } from "geojson";
|
||||||
FeatureCollection,
|
|
||||||
GeoJSON,
|
|
||||||
Geometry,
|
|
||||||
} from "geojson";
|
|
||||||
import * as M from "maplibre-gl";
|
import * as M from "maplibre-gl";
|
||||||
import "maplibre-gl/dist/maplibre-gl.css";
|
import "maplibre-gl/dist/maplibre-gl.css";
|
||||||
import { onDestroy, onMount, untrack } from "svelte";
|
import { onDestroy, onMount, untrack } from "svelte";
|
||||||
@@ -46,7 +43,7 @@
|
|||||||
elevationProfileContainer?: string | HTMLDivElement | undefined;
|
elevationProfileContainer?: string | HTMLDivElement | undefined;
|
||||||
mapOptions?: Partial<M.MapOptions> | undefined;
|
mapOptions?: Partial<M.MapOptions> | undefined;
|
||||||
activeTrail?: number | null;
|
activeTrail?: number | null;
|
||||||
minZoom?: number;
|
clusterTrails?: boolean;
|
||||||
onsegmentdragend?: (data: {
|
onsegmentdragend?: (data: {
|
||||||
segment: number;
|
segment: number;
|
||||||
event: M.MapMouseEvent;
|
event: M.MapMouseEvent;
|
||||||
@@ -57,6 +54,10 @@
|
|||||||
onmoveend?: (map: M.Map) => void;
|
onmoveend?: (map: M.Map) => void;
|
||||||
onzoom?: (map: M.Map) => void;
|
onzoom?: (map: M.Map) => void;
|
||||||
onclick?: (event: M.MapMouseEvent & Object) => void;
|
onclick?: (event: M.MapMouseEvent & Object) => void;
|
||||||
|
onUnclusteredClick?: (
|
||||||
|
event: M.MapMouseEvent & Object,
|
||||||
|
trail: Trail,
|
||||||
|
) => void;
|
||||||
oninit?: (map: M.Map) => void;
|
oninit?: (map: M.Map) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@
|
|||||||
elevationProfileContainer = undefined,
|
elevationProfileContainer = undefined,
|
||||||
mapOptions = undefined,
|
mapOptions = undefined,
|
||||||
activeTrail = $bindable(0),
|
activeTrail = $bindable(0),
|
||||||
minZoom = 0,
|
clusterTrails = false,
|
||||||
onmarkerdragend,
|
onmarkerdragend,
|
||||||
onsegmentdragend,
|
onsegmentdragend,
|
||||||
onselect,
|
onselect,
|
||||||
@@ -85,6 +86,7 @@
|
|||||||
onmoveend,
|
onmoveend,
|
||||||
onzoom,
|
onzoom,
|
||||||
onclick,
|
onclick,
|
||||||
|
onUnclusteredClick,
|
||||||
oninit,
|
oninit,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
@@ -99,6 +101,7 @@
|
|||||||
endMarker: M.Marker | null;
|
endMarker: M.Marker | null;
|
||||||
source: M.GeoJSONSource | null;
|
source: M.GeoJSONSource | null;
|
||||||
layer: M.LineLayerSpecification | null;
|
layer: M.LineLayerSpecification | null;
|
||||||
|
highlighted: boolean;
|
||||||
listener: {
|
listener: {
|
||||||
onEnter: ((e: M.MapMouseEvent) => void) | null;
|
onEnter: ((e: M.MapMouseEvent) => void) | null;
|
||||||
onLeave: ((e: M.MapMouseEvent) => void) | null;
|
onLeave: ((e: M.MapMouseEvent) => void) | null;
|
||||||
@@ -130,7 +133,9 @@
|
|||||||
"#DE7DC5",
|
"#DE7DC5",
|
||||||
];
|
];
|
||||||
|
|
||||||
let data = $derived(getData(trails));
|
let clusterPopup: M.Popup | null = null;
|
||||||
|
|
||||||
|
let [data, clusterData] = $derived(getData(trails));
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (data && map) {
|
if (data && map) {
|
||||||
untrack(() => initMap(map?.loaded() ?? false));
|
untrack(() => initMap(map?.loaded() ?? false));
|
||||||
@@ -182,27 +187,21 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function getData(trails: Trail[]) {
|
function getData(trails: Trail[]): [GeoJSON[], FeatureCollection] {
|
||||||
if (!trails.length) {
|
let cD: FeatureCollection = { type: "FeatureCollection", features: [] };
|
||||||
return [];
|
let r: GeoJSON[] = [];
|
||||||
}
|
|
||||||
|
|
||||||
let r: GeoJSON[] =
|
|
||||||
(map?.getZoom() ?? 0) > minZoom
|
|
||||||
? []
|
|
||||||
: [{ type: "FeatureCollection", features: [] }];
|
|
||||||
trails.forEach((t) => {
|
trails.forEach((t) => {
|
||||||
if ((map?.getZoom() ?? 0) > minZoom) {
|
if (t.expand?.gpx_data) {
|
||||||
if (t.polyline) {
|
r.push(toGeoJson(t.expand.gpx_data) as GeoJSON);
|
||||||
r.push(polylineToGeoJSON(t.polyline, 5));
|
}
|
||||||
} else if (t.expand?.gpx_data) {
|
if (clusterTrails && t.lat !== null && t.lon !== null) {
|
||||||
r.push(toGeoJson(t.expand.gpx_data) as GeoJSON);
|
cD.features.push({
|
||||||
}
|
|
||||||
} else if (t.lat !== null && t.lon !== null) {
|
|
||||||
(r[0] as FeatureCollection).features.push({
|
|
||||||
id: t.id,
|
id: t.id,
|
||||||
type: "Feature",
|
type: "Feature",
|
||||||
properties: {},
|
properties: {
|
||||||
|
trail: t.id,
|
||||||
|
},
|
||||||
geometry: {
|
geometry: {
|
||||||
type: "Point",
|
type: "Point",
|
||||||
coordinates: [t.lon ?? 0, t.lat ?? 0],
|
coordinates: [t.lon ?? 0, t.lat ?? 0],
|
||||||
@@ -211,7 +210,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return r;
|
return [r, cD];
|
||||||
}
|
}
|
||||||
|
|
||||||
function initMap(mapLoaded: boolean) {
|
function initMap(mapLoaded: boolean) {
|
||||||
@@ -226,13 +225,12 @@
|
|||||||
epc?.hideProfile();
|
epc?.hideProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((map?.getZoom() ?? 0) > minZoom) {
|
trails.forEach((t, i) => {
|
||||||
trails.forEach((t, i) => {
|
const layerId = t.id!;
|
||||||
const layerId = t.id!;
|
addTrailLayer(t, layerId, i, data[i]);
|
||||||
addTrailLayer(t, layerId, i, data[i]);
|
});
|
||||||
});
|
if (clusterTrails) {
|
||||||
} else {
|
addClusterLayer(clusterData);
|
||||||
addClusterLayer(data[0] as FeatureCollection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(layers).forEach((layerId) => {
|
Object.keys(layers).forEach((layerId) => {
|
||||||
@@ -279,7 +277,12 @@
|
|||||||
maxY = Math.max(maxY, yMax);
|
maxY = Math.max(maxY, yMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(minX < Infinity && minY < Infinity && maxX > -Infinity && maxY > -Infinity) {
|
if (
|
||||||
|
minX < Infinity &&
|
||||||
|
minY < Infinity &&
|
||||||
|
maxX > -Infinity &&
|
||||||
|
maxY > -Infinity
|
||||||
|
) {
|
||||||
return new M.LngLatBounds([minX, minY, maxX, maxY]);
|
return new M.LngLatBounds([minX, minY, maxX, maxY]);
|
||||||
} else {
|
} else {
|
||||||
return new M.LngLatBounds([0, 0, 0, 0]);
|
return new M.LngLatBounds([0, 0, 0, 0]);
|
||||||
@@ -342,6 +345,7 @@
|
|||||||
endMarker: null,
|
endMarker: null,
|
||||||
source: null,
|
source: null,
|
||||||
layer: null,
|
layer: null,
|
||||||
|
highlighted: false,
|
||||||
listener: {
|
listener: {
|
||||||
onMouseUp: null,
|
onMouseUp: null,
|
||||||
onMouseDown: null,
|
onMouseDown: null,
|
||||||
@@ -384,7 +388,6 @@
|
|||||||
id: id,
|
id: id,
|
||||||
type: "line",
|
type: "line",
|
||||||
source: id,
|
source: id,
|
||||||
minzoom: minZoom,
|
|
||||||
paint: {
|
paint: {
|
||||||
"line-color": trailColors[index % trailColors.length],
|
"line-color": trailColors[index % trailColors.length],
|
||||||
"line-width": 5,
|
"line-width": 5,
|
||||||
@@ -407,7 +410,7 @@
|
|||||||
map.on("mousedown", id, layers[id].listener.onMouseDown);
|
map.on("mousedown", id, layers[id].listener.onMouseDown);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!drawing) {
|
if (!drawing && !clusterTrails) {
|
||||||
addStartEndMarkers(trail, id, geojson);
|
addStartEndMarkers(trail, id, geojson);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -421,7 +424,6 @@
|
|||||||
type: "geojson",
|
type: "geojson",
|
||||||
data: geojson,
|
data: geojson,
|
||||||
cluster: true,
|
cluster: true,
|
||||||
clusterMaxZoom: minZoom - 1,
|
|
||||||
clusterRadius: 50,
|
clusterRadius: 50,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -438,11 +440,17 @@
|
|||||||
"circle-radius": [
|
"circle-radius": [
|
||||||
"step",
|
"step",
|
||||||
["get", "point_count"],
|
["get", "point_count"],
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
15,
|
||||||
20,
|
20,
|
||||||
|
20,
|
||||||
|
50,
|
||||||
|
25,
|
||||||
100,
|
100,
|
||||||
30,
|
30,
|
||||||
750,
|
200,
|
||||||
40,
|
35,
|
||||||
],
|
],
|
||||||
"circle-stroke-width": 3,
|
"circle-stroke-width": 3,
|
||||||
"circle-stroke-color": "#fff",
|
"circle-stroke-color": "#fff",
|
||||||
@@ -461,7 +469,6 @@
|
|||||||
"text-size": 12,
|
"text-size": 12,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
map.addLayer({
|
map.addLayer({
|
||||||
id: "unclustered-point",
|
id: "unclustered-point",
|
||||||
type: "circle",
|
type: "circle",
|
||||||
@@ -477,6 +484,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addClusterHighlightLayer(geojson: GeoJSON) {
|
||||||
|
if (!geojson || !map || !map.style) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!map.getSource("cluster-highlight")) {
|
||||||
|
map.addSource("cluster-highlight", {
|
||||||
|
type: "geojson",
|
||||||
|
data: geojson,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
(map.getSource("cluster-highlight") as M.GeoJSONSource).setData(
|
||||||
|
geojson,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!map.getLayer("cluster-highlight")) {
|
||||||
|
map.addLayer({
|
||||||
|
id: "cluster-highlight",
|
||||||
|
type: "line",
|
||||||
|
source: "cluster-highlight",
|
||||||
|
paint: {
|
||||||
|
"line-color": trailColors[0],
|
||||||
|
"line-width": 5,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function moveCrosshairToCursorPosition(e: M.MapMouseEvent) {
|
function moveCrosshairToCursorPosition(e: M.MapMouseEvent) {
|
||||||
epc?.moveCrosshair(e.lngLat.lat, e.lngLat.lng);
|
epc?.moveCrosshair(e.lngLat.lat, e.lngLat.lng);
|
||||||
moveElevationMarkerToCursorPosition(e);
|
moveElevationMarkerToCursorPosition(e);
|
||||||
@@ -534,7 +569,7 @@
|
|||||||
"interpolate",
|
"interpolate",
|
||||||
["exponential", 1.5],
|
["exponential", 1.5],
|
||||||
["zoom"],
|
["zoom"],
|
||||||
minZoom,
|
0,
|
||||||
80,
|
80,
|
||||||
18,
|
18,
|
||||||
200,
|
200,
|
||||||
@@ -544,7 +579,7 @@
|
|||||||
"interpolate",
|
"interpolate",
|
||||||
["exponential", 1.5],
|
["exponential", 1.5],
|
||||||
["zoom"],
|
["zoom"],
|
||||||
minZoom,
|
0,
|
||||||
0.5,
|
0.5,
|
||||||
18,
|
18,
|
||||||
0.8,
|
0.8,
|
||||||
@@ -590,6 +625,34 @@
|
|||||||
// map?.setPaintProperty(id, "line-color", "#648ad5");
|
// map?.setPaintProperty(id, "line-color", "#648ad5");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function highlightCluster(trail: Trail) {
|
||||||
|
if (!map || !map.style) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clusterPopup = createPopupFromTrail(trail);
|
||||||
|
clusterPopup.setLngLat([trail.lon!, trail.lat!]).addTo(map);
|
||||||
|
|
||||||
|
const geojson = await fetchGPX(trail);
|
||||||
|
|
||||||
|
addClusterHighlightLayer(toGeoJson(geojson));
|
||||||
|
|
||||||
|
clusterPopup.on("close", () => {
|
||||||
|
unHighlightCluster(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function unHighlightCluster(closePopup: boolean = true) {
|
||||||
|
if (!map || !map.style) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (map?.getLayer("cluster-highlight")) {
|
||||||
|
map?.removeLayer("cluster-highlight");
|
||||||
|
}
|
||||||
|
if (closePopup) {
|
||||||
|
clusterPopup?.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function adjustTrailFocus(activeTrail: number | null) {
|
function adjustTrailFocus(activeTrail: number | null) {
|
||||||
if (activeTrail !== null && trails[activeTrail] !== undefined) {
|
if (activeTrail !== null && trails[activeTrail] !== undefined) {
|
||||||
if (
|
if (
|
||||||
@@ -658,7 +721,7 @@
|
|||||||
}
|
}
|
||||||
map.getCanvas().style.cursor = "inherit";
|
map.getCanvas().style.cursor = "inherit";
|
||||||
|
|
||||||
if (activeTrail !== null && trails[activeTrail]) {
|
if (activeTrail !== null && trails[activeTrail] && !clusterTrails) {
|
||||||
addStartEndMarkers(
|
addStartEndMarkers(
|
||||||
trails[activeTrail],
|
trails[activeTrail],
|
||||||
trails[activeTrail].id,
|
trails[activeTrail].id,
|
||||||
@@ -710,7 +773,7 @@
|
|||||||
layers[id].endMarker.setLngLat(
|
layers[id].endMarker.setLngLat(
|
||||||
startEndPoint[startEndPoint.length - 1] as M.LngLatLike,
|
startEndPoint[startEndPoint.length - 1] as M.LngLatLike,
|
||||||
);
|
);
|
||||||
if (map.getZoom() > minZoom) {
|
if (!clusterTrails) {
|
||||||
layers[id].endMarker.addTo(map);
|
layers[id].endMarker.addTo(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -727,16 +790,6 @@
|
|||||||
layers[id].endMarker?.remove();
|
layers[id].endMarker?.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function togglePopup(id: string, currentState?: boolean) {
|
|
||||||
if (
|
|
||||||
currentState !== undefined &&
|
|
||||||
layers[id]?.startMarker?.getPopup().isOpen() != currentState
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
layers[id]?.startMarker?.togglePopup();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showWaypoints() {
|
function showWaypoints() {
|
||||||
if (!map) {
|
if (!map) {
|
||||||
return;
|
return;
|
||||||
@@ -1014,17 +1067,6 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
map.on("zoom", (e) => {
|
map.on("zoom", (e) => {
|
||||||
const zoom = e.target.getZoom();
|
|
||||||
Object.values(layers).forEach((l) => {
|
|
||||||
if (zoom > minZoom && map && !drawing) {
|
|
||||||
l.startMarker?.addTo(map);
|
|
||||||
l.endMarker?.addTo(map);
|
|
||||||
} else {
|
|
||||||
l.startMarker?.remove();
|
|
||||||
l.endMarker?.remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onzoom?.(e.target);
|
onzoom?.(e.target);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1035,6 +1077,51 @@
|
|||||||
onclick?.(e);
|
onclick?.(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
map.on("click", "clusters", async (e) => {
|
||||||
|
if (!map) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const features = map.queryRenderedFeatures(e.point, {
|
||||||
|
layers: ["clusters"],
|
||||||
|
});
|
||||||
|
const clusterId = features[0].properties.cluster_id;
|
||||||
|
const zoom = await (
|
||||||
|
map.getSource("trails") as M.GeoJSONSource
|
||||||
|
).getClusterExpansionZoom(clusterId);
|
||||||
|
map.flyTo({
|
||||||
|
center: (features[0].geometry as any).coordinates,
|
||||||
|
zoom,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
map.on(
|
||||||
|
"click",
|
||||||
|
"unclustered-point",
|
||||||
|
async (e: M.MapMouseEvent & Object) => {
|
||||||
|
const trail = trails.find(
|
||||||
|
(t) => t.id == (e as any).features[0].properties.trail,
|
||||||
|
);
|
||||||
|
if (!trail || !map) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
highlightCluster(trail);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
map.on("mouseenter", "clusters", () => {
|
||||||
|
map!.getCanvas().style.cursor = "pointer";
|
||||||
|
});
|
||||||
|
map.on("mouseleave", "clusters", () => {
|
||||||
|
map!.getCanvas().style.cursor = "";
|
||||||
|
});
|
||||||
|
|
||||||
|
map.on("mouseenter", "unclustered-point", () => {
|
||||||
|
map!.getCanvas().style.cursor = "pointer";
|
||||||
|
});
|
||||||
|
map.on("mouseleave", "unclustered-point", () => {
|
||||||
|
map!.getCanvas().style.cursor = "";
|
||||||
|
});
|
||||||
|
|
||||||
map.on("load", () => {
|
map.on("load", () => {
|
||||||
initMap(true);
|
initMap(true);
|
||||||
oninit?.(map!);
|
oninit?.(map!);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ export type TrailSearchResult = {
|
|||||||
location: string;
|
location: string;
|
||||||
name: string;
|
name: string;
|
||||||
public: boolean;
|
public: boolean;
|
||||||
|
polyline?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ListSearchResult = {
|
export type ListSearchResult = {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export function splitMultiLineStringToLineStrings(geojson: GeoJsonObject): Featu
|
|||||||
...feature.properties,
|
...feature.properties,
|
||||||
coordinateProperties: {
|
coordinateProperties: {
|
||||||
...feature.properties.coordinateProperties,
|
...feature.properties.coordinateProperties,
|
||||||
times: feature.properties.coordinateProperties.times[lineIndex]
|
times: feature.properties.coordinateProperties?.times?.[lineIndex]
|
||||||
},
|
},
|
||||||
featureId: features.length,
|
featureId: features.length,
|
||||||
segmentId: lineIndex,
|
segmentId: lineIndex,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
import TrailFilterPanel from "$lib/components/trail/trail_filter_panel.svelte";
|
import TrailFilterPanel from "$lib/components/trail/trail_filter_panel.svelte";
|
||||||
import type { Settings } from "$lib/models/settings";
|
import type { Settings } from "$lib/models/settings";
|
||||||
import {
|
import {
|
||||||
defaultTrailSearchAttributes,
|
defaultTrailSearchAttributes,
|
||||||
type Trail,
|
type Trail,
|
||||||
type TrailBoundingBox,
|
type TrailBoundingBox,
|
||||||
type TrailFilter,
|
type TrailFilter,
|
||||||
@@ -24,11 +24,12 @@
|
|||||||
type LocationSearchResult,
|
type LocationSearchResult,
|
||||||
type TrailSearchResult,
|
type TrailSearchResult,
|
||||||
} from "$lib/stores/search_store";
|
} from "$lib/stores/search_store";
|
||||||
import { trails_search_bounding_box } from "$lib/stores/trail_store";
|
import {
|
||||||
|
trails_search_bounding_box
|
||||||
|
} from "$lib/stores/trail_store";
|
||||||
import { getIconForLocation } from "$lib/util/icon_util";
|
import { getIconForLocation } from "$lib/util/icon_util";
|
||||||
import type { Snapshot } from "@sveltejs/kit";
|
import type { Snapshot } from "@sveltejs/kit";
|
||||||
import * as M from "maplibre-gl";
|
import * as M from "maplibre-gl";
|
||||||
import { onMount } from "svelte";
|
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { slide } from "svelte/transition";
|
import { slide } from "svelte/transition";
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@
|
|||||||
const maxBoundingBox: TrailBoundingBox = page.data.boundingBox;
|
const maxBoundingBox: TrailBoundingBox = page.data.boundingBox;
|
||||||
const settings: Settings = page.data.settings;
|
const settings: Settings = page.data.settings;
|
||||||
|
|
||||||
const MIN_ZOOM = 6;
|
const MIN_ZOOM = 100;
|
||||||
|
|
||||||
let loading: boolean = $state(true);
|
let loading: boolean = $state(true);
|
||||||
let loadingNextPage: boolean = false;
|
let loadingNextPage: boolean = false;
|
||||||
@@ -57,7 +58,7 @@
|
|||||||
|
|
||||||
export const snapshot: Snapshot<TrailFilter> = {
|
export const snapshot: Snapshot<TrailFilter> = {
|
||||||
capture: () => filter,
|
capture: () => filter,
|
||||||
restore: (value) => {
|
restore: (value) => {
|
||||||
filter = value;
|
filter = value;
|
||||||
handleFilterUpdate();
|
handleFilterUpdate();
|
||||||
},
|
},
|
||||||
@@ -140,11 +141,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleTrailCardMouseEnter(trail: Trail) {
|
function handleTrailCardMouseEnter(trail: Trail) {
|
||||||
mapWithElevation?.togglePopup(trail.id!, false);
|
mapWithElevation?.highlightCluster(trail);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTrailCardMouseLeave(trail: Trail) {
|
function handleTrailCardMouseLeave(trail: Trail) {
|
||||||
mapWithElevation?.togglePopup(trail.id!, true);
|
mapWithElevation?.unHighlightCluster();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleFilterUpdate() {
|
async function handleFilterUpdate() {
|
||||||
@@ -356,7 +357,7 @@
|
|||||||
showInfoPopup={true}
|
showInfoPopup={true}
|
||||||
activeTrail={-1}
|
activeTrail={-1}
|
||||||
fitBounds="off"
|
fitBounds="off"
|
||||||
minZoom={MIN_ZOOM}
|
clusterTrails={true}
|
||||||
bind:map
|
bind:map
|
||||||
bind:this={mapWithElevation}
|
bind:this={mapWithElevation}
|
||||||
></MapWithElevationMaplibre>
|
></MapWithElevationMaplibre>
|
||||||
|
|||||||
Reference in New Issue
Block a user