adds terrain to map
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
import { createEventDispatcher, onDestroy, onMount } from "svelte";
|
||||
import MaplibreGraticule from "$lib/vendor/maplibre-graticule/maplibre-graticule";
|
||||
import { FullscreenControl } from "$lib/vendor/maplibre-fullscreen/fullscreen-control";
|
||||
import type { Settings } from "$lib/models/settings";
|
||||
|
||||
export let trails: Trail[] = [];
|
||||
export let markers: M.Marker[] = [];
|
||||
@@ -27,6 +28,7 @@
|
||||
export let showGrid: boolean = false;
|
||||
export let showStyleSwitcher: boolean = true;
|
||||
export let showFullscreen: boolean = false;
|
||||
export let showTerrain: boolean = false;
|
||||
export let fitBounds: "animate" | "instant" | "off" = "instant";
|
||||
|
||||
export let elevationProfileContainer: string | HTMLDivElement | undefined =
|
||||
@@ -194,6 +196,11 @@
|
||||
const bounds = data[activeTrail]
|
||||
? (data[activeTrail].bbox as M.LngLatBoundsLike)
|
||||
: getBounds();
|
||||
|
||||
if (!bounds) {
|
||||
return;
|
||||
}
|
||||
|
||||
map!.fitBounds(bounds, {
|
||||
animate: animate,
|
||||
padding: {
|
||||
@@ -336,8 +343,6 @@
|
||||
dispatch("select", trail);
|
||||
const index = trails.findIndex((t) => t.id == trail.id);
|
||||
if (index == -1) {
|
||||
console.log("here");
|
||||
|
||||
return;
|
||||
}
|
||||
activeTrail = index;
|
||||
@@ -425,30 +430,37 @@
|
||||
)
|
||||
).ElevationProfileControl;
|
||||
|
||||
const mapStyles = [
|
||||
{
|
||||
text: "Open Street Maps",
|
||||
value: "/styles/osm.json",
|
||||
thumbnail: "https://tile.openstreetmap.org/1/0/0.png",
|
||||
},
|
||||
{
|
||||
text: "Open Topo Maps",
|
||||
value: "/styles/otm.json",
|
||||
thumbnail: "https://tile.opentopomap.org/1/0/0.png",
|
||||
},
|
||||
{
|
||||
text: "Carto Light",
|
||||
value: "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json",
|
||||
thumbnail:
|
||||
"https://basemaps.cartocdn.com/light_all/1/0/0@2x.png",
|
||||
},
|
||||
{
|
||||
text: "Carto Dark",
|
||||
value: "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json",
|
||||
thumbnail:
|
||||
"https://basemaps.cartocdn.com/dark_all/1/0/0@2x.png",
|
||||
},
|
||||
];
|
||||
const mapStyles: { text: string; value: string; thumbnail?: string }[] =
|
||||
[
|
||||
...(($page.data.settings as Settings).tilesets ?? []).map(
|
||||
(t) => ({
|
||||
text: t.name,
|
||||
value: t.url,
|
||||
}),
|
||||
),
|
||||
{
|
||||
text: "Open Street Maps",
|
||||
value: "/styles/osm.json",
|
||||
thumbnail: "https://tile.openstreetmap.org/1/0/0.png",
|
||||
},
|
||||
{
|
||||
text: "Open Topo Maps",
|
||||
value: "/styles/otm.json",
|
||||
thumbnail: "https://tile.opentopomap.org/1/0/0.png",
|
||||
},
|
||||
{
|
||||
text: "Carto Light",
|
||||
value: "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json",
|
||||
thumbnail:
|
||||
"https://basemaps.cartocdn.com/light_all/1/0/0@2x.png",
|
||||
},
|
||||
{
|
||||
text: "Carto Dark",
|
||||
value: "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json",
|
||||
thumbnail:
|
||||
"https://basemaps.cartocdn.com/dark_all/1/0/0@2x.png",
|
||||
},
|
||||
];
|
||||
const preferredMapStyleIndex = mapStyles.findIndex(
|
||||
(s) => s.text === localStorage.getItem("layer"),
|
||||
);
|
||||
@@ -490,7 +502,9 @@
|
||||
selectedIndex:
|
||||
preferredMapStyleIndex !== -1 ? preferredMapStyleIndex : 0,
|
||||
});
|
||||
map.addControl(new M.NavigationControl());
|
||||
map.addControl(
|
||||
new M.NavigationControl({ visualizePitch: showTerrain }),
|
||||
);
|
||||
map.addControl(
|
||||
new M.ScaleControl({
|
||||
maxWidth: 120,
|
||||
@@ -536,10 +550,25 @@
|
||||
);
|
||||
}
|
||||
|
||||
if (showTerrain) {
|
||||
map!.addControl(
|
||||
new M.TerrainControl({
|
||||
source: "terrain",
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
map.on("styledata", () => {
|
||||
trails.forEach((t, i) => {
|
||||
addTrailLayer(t, t.id ?? i.toString(), data?.at(i));
|
||||
});
|
||||
|
||||
if (showTerrain && $page.data.settings?.terrain) {
|
||||
map!.addSource("terrain", {
|
||||
type: "raster-dem",
|
||||
url: $page.data.settings.terrain,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
map.on("moveend", (e) => {
|
||||
|
||||
@@ -7,6 +7,7 @@ class Settings {
|
||||
location?: { name: string, lat: number, lon: number };
|
||||
category?: string;
|
||||
tilesets?: {name: string, url: string}[]
|
||||
terrain?: string;
|
||||
user?: string;
|
||||
|
||||
constructor(
|
||||
@@ -18,6 +19,7 @@ class Settings {
|
||||
location?: { name: string, lat: number, lon: number }
|
||||
category?: string
|
||||
tilesets?: {name: string, url: string}[]
|
||||
terrain?: string;
|
||||
}
|
||||
) {
|
||||
this.unit = unit;
|
||||
@@ -27,6 +29,7 @@ class Settings {
|
||||
this.location = params?.location;
|
||||
this.category = params?.category;
|
||||
this.tilesets = params?.tilesets ?? [];
|
||||
this.terrain = params?.terrain;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ export function createPopupFromTrail(trail: Trail) {
|
||||
: "/imgs/default_thumbnail.webp";
|
||||
const popup = new M.Popup({maxWidth: "320px"});
|
||||
popup.setHTML(
|
||||
`<a href="/trail/view/${trail.id}" data-sveltekit-preload-data="off">
|
||||
`<a href="/map/trail/${trail.id}" data-sveltekit-preload-data="off">
|
||||
<li class="flex items-center gap-4 cursor-pointer text-black max-w-80">
|
||||
<div class="shrink-0"><img class="h-14 w-14 object-cover rounded-xl" src="${thumbnail}" alt="">
|
||||
</div>
|
||||
|
||||
@@ -415,7 +415,6 @@ export class ElevationProfile {
|
||||
|
||||
Chart.register(...registerables);
|
||||
Chart.register(zoomPlugin);
|
||||
Chart.register(CrosshairPlugin);
|
||||
|
||||
this.settings = {
|
||||
...elevationProfileDefaultOptions,
|
||||
@@ -676,6 +675,7 @@ export class ElevationProfile {
|
||||
},
|
||||
|
||||
plugins: [
|
||||
CrosshairPlugin,
|
||||
{
|
||||
id: "waypointPlugin",
|
||||
afterDraw: (chart, args, options) => {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { type ControlPosition, type IControl } from "maplibre-gl";
|
||||
type MapStyle = {
|
||||
text: string;
|
||||
value: string;
|
||||
thumbnail: string;
|
||||
thumbnail?: string;
|
||||
}
|
||||
|
||||
export type StyleSwitcherControlOptions = {
|
||||
@@ -73,20 +73,30 @@ export class StyleSwitcherControl implements IControl {
|
||||
this.switcherContainer.appendChild(headingDiv)
|
||||
|
||||
const buttonDiv = document.createElement("ul")
|
||||
buttonDiv.classList.add("mt-2");
|
||||
buttonDiv.classList.add("mt-2", "max-h-64", "overflow-y-scroll");
|
||||
this.settings.styles.forEach((style, i) => {
|
||||
const styleLi = document.createElement("li");
|
||||
styleLi.classList.add("flex", "items-center", "gap-x-4", "px-3", "py-2", "cursor-pointer", "hover:bg-menu-item-background-hover")
|
||||
const styleImg = document.createElement("img");
|
||||
styleImg.classList.add("w-12", "h-12", "rounded-md")
|
||||
styleImg.src = style.thumbnail;
|
||||
if (style.thumbnail) {
|
||||
const styleImg = document.createElement("img");
|
||||
styleImg.classList.add("w-12", "h-12", "rounded-md")
|
||||
styleImg.src = style.thumbnail;
|
||||
styleLi.appendChild(styleImg)
|
||||
} else {
|
||||
const styleIconContainer = document.createElement("i");
|
||||
styleIconContainer.classList.add("w-12", "h-12", "rounded-md", "bg-blue-200", "flex", "items-center", "justify-center")
|
||||
const styleIcon = document.createElement("i");
|
||||
styleIcon.classList.add("fa", "fa-map-location-dot", "text-xl")
|
||||
styleIconContainer.appendChild(styleIcon)
|
||||
styleLi.appendChild(styleIconContainer)
|
||||
}
|
||||
|
||||
const styleName = document.createElement("span");
|
||||
styleName.classList.add("!text-sm")
|
||||
if (i == this.settings.selectedIndex) {
|
||||
styleName.classList.add("font-semibold")
|
||||
}
|
||||
styleName.textContent = style.text;
|
||||
styleLi.appendChild(styleImg)
|
||||
styleLi.appendChild(styleName)
|
||||
|
||||
styleLi.addEventListener("click", () => {
|
||||
|
||||
Reference in New Issue
Block a user