mobilizon.chapril.org-mobil.../js/src/components/Map.vue

174 lines
4.0 KiB
Vue
Raw Normal View History

<template>
<div class="map-container" v-if="config">
<l-map
:zoom="mergedOptions.zoom"
:style="`height: ${mergedOptions.height}; width: ${mergedOptions.width}`"
class="leaflet-map"
:center="[lat, lon]"
@click="clickMap"
@update:zoom="updateZoom"
:options="{ zoomControl: false }"
>
<l-tile-layer
:url="config.maps.tiles.endpoint"
:attribution="attribution"
>
</l-tile-layer>
<l-control-zoom
position="topleft"
:zoomInTitle="$t('Zoom in')"
:zoomOutTitle="$t('Zoom out')"
></l-control-zoom>
<v-locatecontrol
v-if="canDoGeoLocation"
:options="{ icon: 'mdi mdi-map-marker' }"
/>
<l-marker
:lat-lng="[lat, lon]"
@add="openPopup"
@update:latLng="updateDraggableMarkerPosition"
:draggable="!readOnly"
>
<l-popup v-if="popupMultiLine">
<span v-for="line in popupMultiLine" :key="line"
>{{ line }}<br
/></span>
</l-popup>
</l-marker>
</l-map>
</div>
</template>
<script lang="ts">
import { Icon, LatLng, LeafletMouseEvent, LeafletEvent } from "leaflet";
import "leaflet/dist/leaflet.css";
import { Component, Prop, Vue } from "vue-property-decorator";
import {
LMap,
LTileLayer,
LMarker,
LPopup,
LIcon,
LControlZoom,
} from "vue2-leaflet";
import Vue2LeafletLocateControl from "@/components/Map/Vue2LeafletLocateControl.vue";
import { CONFIG } from "../graphql/config";
import { IConfig } from "../types/config.model";
@Component({
components: {
LTileLayer,
LMap,
LMarker,
LPopup,
LIcon,
LControlZoom,
"v-locatecontrol": Vue2LeafletLocateControl,
},
apollo: {
config: CONFIG,
},
})
export default class Map extends Vue {
@Prop({ type: Boolean, required: false, default: true }) readOnly!: boolean;
@Prop({ type: String, required: true }) coords!: string;
@Prop({ type: Object, required: false }) marker!: {
text: string | string[];
icon: string;
};
@Prop({ type: Object, required: false }) options!: Record<string, unknown>;
@Prop({ type: Function, required: false })
updateDraggableMarkerCallback!: (latlng: LatLng, zoom: number) => void;
defaultOptions: {
zoom: number;
height: string;
width: string;
} = {
zoom: 15,
height: "100%",
width: "100%",
};
zoom = this.defaultOptions.zoom;
config!: IConfig;
/* eslint-disable */
mounted() {
// this part resolve an issue where the markers would not appear
// @ts-ignore
delete Icon.Default.prototype._getIconUrl;
Icon.Default.mergeOptions({
iconRetinaUrl: require("leaflet/dist/images/marker-icon-2x.png"),
iconUrl: require("leaflet/dist/images/marker-icon.png"),
shadowUrl: require("leaflet/dist/images/marker-shadow.png"),
});
}
/* eslint-enable */
openPopup(event: LeafletEvent): void {
this.$nextTick(() => {
event.target.openPopup();
});
}
get mergedOptions(): Record<string, unknown> {
return { ...this.defaultOptions, ...this.options };
}
get lat(): number {
return this.$props.coords.split(";")[1];
}
get lon(): number {
return this.$props.coords.split(";")[0];
}
get popupMultiLine(): Array<string> {
if (Array.isArray(this.marker.text)) {
return this.marker.text;
}
return [this.marker.text];
}
clickMap(event: LeafletMouseEvent): void {
this.updateDraggableMarkerPosition(event.latlng);
}
updateDraggableMarkerPosition(e: LatLng): void {
this.updateDraggableMarkerCallback(e, this.zoom);
}
updateZoom(zoom: number): void {
this.zoom = zoom;
}
get attribution(): string {
return (
this.config.maps.tiles.attribution ||
(this.$t("© The OpenStreetMap Contributors") as string)
);
}
get canDoGeoLocation(): boolean {
return window.isSecureContext;
}
}
</script>
<style lang="scss" scoped>
div.map-container {
height: 100%;
width: 100%;
.leaflet-map {
z-index: 20;
}
}
</style>