Files
gpx.studio/website/src/lib/components/Map.svelte

294 lines
6.2 KiB
Svelte
Raw Normal View History

2024-04-05 17:53:42 +02:00
<script lang="ts">
2024-07-08 16:21:19 +02:00
import { onDestroy, onMount } from 'svelte';
2024-04-05 17:53:42 +02:00
2024-04-10 14:54:35 +02:00
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
2024-04-05 17:53:42 +02:00
2024-04-10 14:54:35 +02:00
import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder';
import '@mapbox/mapbox-gl-geocoder/dist/mapbox-gl-geocoder.css';
2024-04-05 17:53:42 +02:00
2024-05-04 15:10:30 +02:00
import { map } from '$lib/stores';
import { settings } from '$lib/db';
2024-04-24 17:39:56 +02:00
import { locale } from 'svelte-i18n';
import { get } from 'svelte/store';
2024-05-08 21:31:54 +02:00
import { mapboxAccessToken } from '$lib/assets/layers';
2024-04-17 11:44:37 +02:00
2024-05-08 21:31:54 +02:00
mapboxgl.accessToken = mapboxAccessToken;
2024-04-10 14:54:35 +02:00
2024-04-22 10:45:02 +02:00
let fitBoundsOptions: mapboxgl.FitBoundsOptions = {
maxZoom: 15,
linear: true,
easing: () => 1
};
2024-04-05 17:53:42 +02:00
2024-06-25 16:06:11 +02:00
const { distanceUnits, elevationProfile, verticalFileView, bottomPanelSize, rightPanelSize } =
settings;
2024-04-24 16:57:32 +02:00
let scaleControl = new mapboxgl.ScaleControl({
2024-05-04 15:10:30 +02:00
unit: $distanceUnits
2024-04-24 16:57:32 +02:00
});
2024-04-05 17:53:42 +02:00
onMount(() => {
2024-05-04 23:50:27 +02:00
let newMap = new mapboxgl.Map({
2024-04-05 17:53:42 +02:00
container: 'map',
2024-04-11 17:18:21 +02:00
style: { version: 8, sources: {}, layers: [] },
2024-04-12 12:38:19 +02:00
projection: { name: 'mercator' },
2024-04-10 14:54:35 +02:00
hash: true,
2024-04-24 17:39:56 +02:00
language: get(locale),
2024-04-10 14:54:35 +02:00
attributionControl: false,
2024-04-20 18:47:16 +02:00
logoPosition: 'bottom-right',
boxZoom: false
2024-04-05 17:53:42 +02:00
});
2024-05-04 23:50:27 +02:00
newMap.on('load', () => {
$map = newMap; // only set the store after the map has loaded
2024-07-05 01:02:53 +02:00
scaleControl.setUnit($distanceUnits);
2024-05-04 23:50:27 +02:00
});
2024-04-05 17:53:42 +02:00
2024-05-04 23:50:27 +02:00
newMap.addControl(
2024-04-10 14:54:35 +02:00
new mapboxgl.AttributionControl({
compact: true
2024-04-05 17:53:42 +02:00
})
);
2024-05-04 23:50:27 +02:00
newMap.addControl(new mapboxgl.NavigationControl());
2024-04-10 14:54:35 +02:00
2024-05-04 23:50:27 +02:00
newMap.addControl(
2024-04-10 14:54:35 +02:00
new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
mapboxgl: mapboxgl,
2024-04-22 10:45:02 +02:00
collapsed: true,
2024-04-24 17:39:56 +02:00
flyTo: fitBoundsOptions,
language: get(locale)
2024-04-10 14:54:35 +02:00
})
);
2024-05-04 23:50:27 +02:00
newMap.addControl(
2024-04-10 14:54:35 +02:00
new mapboxgl.GeolocateControl({
2024-04-05 17:53:42 +02:00
positionOptions: {
enableHighAccuracy: true
},
2024-04-22 10:45:02 +02:00
fitBoundsOptions,
2024-04-10 14:54:35 +02:00
trackUserLocation: true,
showUserHeading: true
2024-04-05 17:53:42 +02:00
})
);
2024-05-04 23:50:27 +02:00
newMap.addControl(scaleControl);
2024-04-19 17:26:56 +02:00
2024-05-08 21:51:52 +02:00
newMap.on('style.load', () => {
2024-05-09 00:02:27 +02:00
newMap.addSource('mapbox-dem', {
type: 'raster-dem',
url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
tileSize: 512,
maxzoom: 14
});
newMap.setTerrain({
source: 'mapbox-dem',
2024-05-17 13:10:20 +02:00
exaggeration: newMap.getPitch() > 0 ? 1 : 0
});
2024-05-09 00:02:27 +02:00
newMap.setFog({
color: 'rgb(186, 210, 235)',
'high-color': 'rgb(36, 92, 223)',
'horizon-blend': 0.1,
'space-color': 'rgb(156, 240, 255)'
});
newMap.on('pitch', () => {
if (newMap.getPitch() > 0) {
newMap.setTerrain({
source: 'mapbox-dem',
exaggeration: 1
});
} else {
newMap.setTerrain({
source: 'mapbox-dem',
exaggeration: 0
});
}
});
2024-05-08 21:51:52 +02:00
// add dummy layer to place the overlay layers below
newMap.addLayer({
id: 'overlays',
type: 'background',
paint: {
'background-color': 'rgba(0, 0, 0, 0)'
}
});
});
2024-04-05 17:53:42 +02:00
});
2024-04-24 16:57:32 +02:00
2024-07-08 16:21:19 +02:00
onDestroy(() => {
if ($map) {
$map.remove();
$map = null;
}
});
2024-06-25 16:06:11 +02:00
$: if (
$map &&
(!$verticalFileView || !$elevationProfile || $bottomPanelSize || $rightPanelSize)
) {
2024-05-23 11:21:57 +02:00
$map.resize();
}
2024-04-05 17:53:42 +02:00
</script>
<div {...$$restProps}>
2024-04-16 22:57:28 +02:00
<div id="map" class="h-full"></div>
2024-04-05 17:53:42 +02:00
</div>
2024-04-10 14:54:35 +02:00
<style lang="postcss">
2024-04-24 12:55:53 +02:00
div :global(.mapboxgl-map) {
@apply font-sans;
}
div :global(.mapboxgl-ctrl-top-right > .mapboxgl-ctrl) {
2024-04-10 14:54:35 +02:00
@apply shadow-md;
2024-04-28 17:01:22 +02:00
@apply bg-background;
@apply text-foreground;
}
div :global(.mapboxgl-ctrl-icon) {
@apply dark:brightness-[4.7];
2024-04-10 14:54:35 +02:00
}
div :global(.mapboxgl-ctrl-geocoder) {
@apply flex;
@apply flex-row;
@apply w-fit;
@apply min-w-fit;
@apply items-center;
@apply shadow-md;
}
div :global(.suggestions) {
@apply shadow-md;
2024-04-28 17:01:22 +02:00
@apply bg-background;
@apply text-foreground;
}
div :global(.mapboxgl-ctrl-geocoder .suggestions > li > a) {
@apply text-foreground;
@apply hover:text-accent-foreground;
@apply hover:bg-accent;
}
div :global(.mapboxgl-ctrl-geocoder .suggestions > .active > a) {
@apply bg-background;
}
div :global(.mapboxgl-ctrl-geocoder--button) {
@apply bg-transparent;
@apply hover:bg-transparent;
}
div :global(.mapboxgl-ctrl-geocoder--icon) {
@apply fill-foreground;
@apply hover:fill-accent-foreground;
2024-04-10 14:54:35 +02:00
}
div :global(.mapboxgl-ctrl-geocoder--icon-search) {
@apply relative;
@apply top-0;
@apply left-0;
@apply my-2;
@apply w-[29px];
}
div :global(.mapboxgl-ctrl-geocoder--input) {
@apply relative;
2024-04-12 18:05:26 +02:00
@apply w-64;
2024-04-10 14:54:35 +02:00
@apply py-0;
@apply pl-2;
@apply focus:outline-none;
2024-04-12 18:05:26 +02:00
@apply transition-[width];
@apply duration-200;
2024-04-28 17:01:22 +02:00
@apply text-foreground;
2024-04-10 14:54:35 +02:00
}
div :global(.mapboxgl-ctrl-geocoder--collapsed .mapboxgl-ctrl-geocoder--input) {
2024-04-12 18:05:26 +02:00
@apply w-0;
@apply p-0;
2024-04-10 14:54:35 +02:00
}
2024-04-12 15:51:57 +02:00
div :global(.mapboxgl-ctrl-top-right) {
2024-04-26 19:34:46 +02:00
@apply z-20;
2024-04-15 11:25:31 +02:00
@apply flex;
@apply flex-col;
@apply items-end;
@apply h-full;
@apply overflow-hidden;
2024-04-12 15:51:57 +02:00
}
2024-04-19 16:13:08 +02:00
2024-05-23 11:21:57 +02:00
.horizontal :global(.mapboxgl-ctrl-bottom-left) {
2024-04-27 11:16:59 +02:00
@apply bottom-[42px];
2024-04-19 16:13:08 +02:00
}
2024-05-23 11:21:57 +02:00
.horizontal :global(.mapboxgl-ctrl-bottom-right) {
2024-04-27 11:16:59 +02:00
@apply bottom-[42px];
2024-04-19 16:13:08 +02:00
}
2024-04-26 13:33:17 +02:00
2024-04-28 17:01:22 +02:00
div :global(.mapboxgl-ctrl-attrib) {
@apply dark:bg-transparent;
}
div :global(.mapboxgl-compact-show.mapboxgl-ctrl-attrib) {
@apply dark:bg-background;
}
div :global(.mapboxgl-ctrl-attrib-button) {
@apply dark:bg-foreground;
}
div :global(.mapboxgl-compact-show .mapboxgl-ctrl-attrib-button) {
@apply dark:bg-foreground;
}
div :global(.mapboxgl-ctrl-attrib a) {
@apply text-foreground;
}
2024-04-26 13:33:17 +02:00
div :global(.mapboxgl-popup) {
@apply w-fit;
2024-04-26 19:34:46 +02:00
@apply z-20;
2024-04-26 13:33:17 +02:00
}
div :global(.mapboxgl-popup-content) {
@apply p-0;
@apply bg-transparent;
@apply shadow-none;
}
2024-06-20 18:13:46 +02:00
div :global(.mapboxgl-popup-anchor-top .mapboxgl-popup-tip) {
@apply border-b-background;
}
div :global(.mapboxgl-popup-anchor-top-left .mapboxgl-popup-tip) {
@apply border-b-background;
}
div :global(.mapboxgl-popup-anchor-top-right .mapboxgl-popup-tip) {
@apply border-b-background;
}
div :global(.mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip) {
@apply border-t-background;
@apply drop-shadow-md;
}
div :global(.mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-tip) {
@apply border-t-background;
2024-04-26 13:33:17 +02:00
@apply drop-shadow-md;
2024-06-20 18:13:46 +02:00
}
div :global(.mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-tip) {
2024-04-28 17:01:22 +02:00
@apply border-t-background;
2024-06-20 18:13:46 +02:00
@apply drop-shadow-md;
}
div :global(.mapboxgl-popup-anchor-left .mapboxgl-popup-tip) {
@apply border-r-background;
}
div :global(.mapboxgl-popup-anchor-right .mapboxgl-popup-tip) {
@apply border-l-background;
2024-04-26 13:33:17 +02:00
}
2024-04-10 14:54:35 +02:00
</style>