nidus-sync/ts/components/MapProxiedArcgisTile.vue

136 lines
2.8 KiB
Vue

<style scoped>
#map {
height: 100%;
width: 100%;
margin-bottom: 10px;
}
.map-container {
height: 100%;
width: 100%;
}
</style>
<template>
<div v-if="error == null">
<div ref="mapContainer" class="map-multipoint"></div>
</div>
<div v-else>
<h1>Map failed to load</h1>
<p>{{ error }}</p>
</div>
</template>
<script setup lang="ts">
import "maplibre-gl/dist/maplibre-gl.css";
import type { LngLatBoundsLike, Map as MapLibreMap } from "maplibre-gl";
import maplibregl from "maplibre-gl";
import {
ref,
watch,
onMounted,
onBeforeUnmount,
shallowRef,
type Ref,
} from "vue";
import { MapClickEvent, Marker, Point } from "@/types";
import type { Location } from "@/type/api";
interface Emits {
(e: "map-click", event: MapClickEvent): void;
}
interface Props {
location: Location;
markers: Marker[];
organizationId: Number;
tegola: string;
urlTiles: string;
}
const emit = defineEmits<Emits>();
const props = defineProps<Props>();
const error = ref<string | null>(null);
const mapContainer = ref<HTMLElement | null>(null);
const map: Ref<MapLibreMap | null> = shallowRef(null);
const markerInstances = ref<Map<string, maplibregl.Marker>>(new Map());
const markers = ref<Map<string, maplibregl.Marker>>(new Map());
// Watch for latitude/longitude changes
watch(
() => [props.location],
([newLocation]) => {
if (map.value) {
map.value.jumpTo({
center: [newLocation.longitude, newLocation.latitude],
zoom: 19,
});
}
},
);
const initializeMap = () => {
if (!mapContainer.value) return;
try {
map.value = new maplibregl.Map({
center: [props.location.longitude, props.location.latitude],
container: mapContainer.value,
style: "https://tiles.stadiamaps.com/styles/osm_bright.json",
zoom: 19,
});
const mapInstance = map.value;
mapInstance.on("load", () => {
if (props.organizationId !== 0) {
mapInstance.addSource("tegola", {
type: "vector",
tiles: [
`${props.tegola}maps/nidus/{z}/{x}/{y}?id=${props.organizationId}&organization_id=${props.organizationId}`,
],
});
mapInstance.addLayer({
id: "service-area",
source: "tegola",
"source-layer": "service-area-bounds",
type: "line",
paint: {
"line-color": "#f00",
},
});
}
mapInstance.addSource("flyover", {
type: "raster",
tiles: [props.urlTiles],
});
mapInstance.addLayer({
id: "flyover-layer",
source: "flyover",
type: "raster",
});
mapInstance.on("click", (e) => {
emit("map-click", {
location: {
latitude: e.lngLat.lat,
longitude: e.lngLat.lng,
},
map: mapInstance,
point: e.point,
});
});
});
} catch (e) {
console.error("hey dummy", e);
}
};
onMounted(() => {
setTimeout(() => initializeMap(), 0);
});
onBeforeUnmount(() => {
if (map.value) {
map.value.remove();
}
});
</script>