2023-03-31 12:54:15 +00:00
|
|
|
<template>
|
|
|
|
<div style="position: relative">
|
|
|
|
<!-- <Map className="h-36" :center="state.center" :zoom="state.zoom"> // map component content </Map> -->
|
2023-12-29 14:54:49 +00:00
|
|
|
<div :id="mapId" class="rounded">
|
|
|
|
<div class="dark:bg-slate-900 bg-slate flex flex-col">
|
|
|
|
<ZoomControlComponent ref="zoom" :mapId="mapId" />
|
|
|
|
<DrawControlComponent ref="draw" :mapId="mapId" :southWest="southWest" :northEast="northEast" />
|
|
|
|
</div>
|
2023-03-31 12:54:15 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
import { EventEmitter } from './EventEmitter';
|
2023-05-02 16:10:32 +00:00
|
|
|
import { Component, Vue, Prop, Ref } from 'vue-facing-decorator';
|
2023-03-31 12:54:15 +00:00
|
|
|
// import type { Coverage } from '@/Dataset';
|
2023-04-06 16:56:41 +00:00
|
|
|
// import { Map, Control, MapOptions, LatLngBoundsExpression, tileLayer, latLng, latLngBounds, FeatureGroup } from 'leaflet';
|
|
|
|
import { Map } from 'leaflet/src/map/index';
|
|
|
|
import { Control } from 'leaflet/src/control/Control';
|
|
|
|
import { LatLngBoundsExpression, toLatLngBounds } from 'leaflet/src/geo/LatLngBounds';
|
|
|
|
import { toLatLng } from 'leaflet/src/geo/LatLng';
|
|
|
|
import { tileLayerWMS } from 'leaflet/src/layer/tile/TileLayer.WMS';
|
|
|
|
import { Attribution } from 'leaflet/src/control/Control.Attribution';
|
|
|
|
// import { Attribution } from 'leaflet';
|
|
|
|
// import { FeatureGroup } from 'leaflet/src/layer/FeatureGroup';
|
|
|
|
|
|
|
|
import { MapOptions } from './MapOptions';
|
|
|
|
import { LayerOptions, LayerMap } from './LayerOptions';
|
|
|
|
import { MapService } from '@/Stores/map.service';
|
2023-03-31 12:54:15 +00:00
|
|
|
import ZoomControlComponent from './zoom.component.vue';
|
2023-04-06 16:56:41 +00:00
|
|
|
import DrawControlComponent from './draw.component.vue';
|
2023-05-02 16:10:32 +00:00
|
|
|
import { Coverage } from '@/Dataset';
|
2023-06-01 12:29:56 +00:00
|
|
|
import { canvas } from 'leaflet/src/layer/vector/Canvas';
|
|
|
|
import { svg } from 'leaflet/src/layer/vector/SVG';
|
2023-05-02 16:10:32 +00:00
|
|
|
|
2023-06-01 12:29:56 +00:00
|
|
|
Map.include({
|
|
|
|
// @namespace Map; @method getRenderer(layer: Path): Renderer
|
|
|
|
// Returns the instance of `Renderer` that should be used to render the given
|
|
|
|
// `Path`. It will ensure that the `renderer` options of the map and paths
|
|
|
|
// are respected, and that the renderers do exist on the map.
|
|
|
|
getRenderer: function (layer) {
|
|
|
|
// @namespace Path; @option renderer: Renderer
|
|
|
|
// Use this specific instance of `Renderer` for this path. Takes
|
|
|
|
// precedence over the map's [default renderer](#map-renderer).
|
|
|
|
var renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer;
|
|
|
|
|
|
|
|
if (!renderer) {
|
|
|
|
renderer = this._renderer = this._createRenderer();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.hasLayer(renderer)) {
|
|
|
|
this.addLayer(renderer);
|
|
|
|
}
|
|
|
|
return renderer;
|
|
|
|
},
|
2023-05-02 16:10:32 +00:00
|
|
|
|
2023-06-01 12:29:56 +00:00
|
|
|
_getPaneRenderer: function (name) {
|
|
|
|
if (name === 'overlayPane' || name === undefined) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var renderer = this._paneRenderers[name];
|
|
|
|
if (renderer === undefined) {
|
|
|
|
renderer = this._createRenderer({ pane: name });
|
|
|
|
this._paneRenderers[name] = renderer;
|
|
|
|
}
|
|
|
|
return renderer;
|
|
|
|
},
|
2023-05-02 16:10:32 +00:00
|
|
|
|
2023-06-01 12:29:56 +00:00
|
|
|
_createRenderer: function (options) {
|
|
|
|
// @namespace Map; @option preferCanvas: Boolean = false
|
|
|
|
// Whether `Path`s should be rendered on a `Canvas` renderer.
|
|
|
|
// By default, all `Path`s are rendered in a `SVG` renderer.
|
|
|
|
return (this.options.preferCanvas && canvas(options)) || svg(options);
|
|
|
|
},
|
2023-05-02 16:10:32 +00:00
|
|
|
});
|
|
|
|
|
2023-03-31 12:54:15 +00:00
|
|
|
const DEFAULT_BASE_LAYER_NAME = 'BaseLayer';
|
|
|
|
// const DEFAULT_BASE_LAYER_URL = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
|
|
|
|
const DEFAULT_BASE_LAYER_ATTRIBUTION = '© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors';
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
name: 'MapComponent',
|
|
|
|
components: {
|
|
|
|
ZoomControlComponent,
|
2023-05-02 16:10:32 +00:00
|
|
|
DrawControlComponent,
|
2023-03-31 12:54:15 +00:00
|
|
|
},
|
|
|
|
})
|
|
|
|
export default class MapComponent extends Vue {
|
|
|
|
/**
|
|
|
|
* A map with the given ID is created inside this component.
|
|
|
|
* This ID can be used the get the map instance over the map cache service.
|
|
|
|
*/
|
|
|
|
@Prop()
|
|
|
|
public mapId: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The corresponding leaflet map options (see: https://leafletjs.com/reference-1.3.4.html#map-option)
|
|
|
|
*/
|
|
|
|
@Prop()
|
|
|
|
public mapOptions: MapOptions;
|
|
|
|
|
2023-05-02 16:10:32 +00:00
|
|
|
@Prop()
|
|
|
|
public coverage: Coverage;
|
|
|
|
|
2023-03-31 12:54:15 +00:00
|
|
|
// markerService: MarkerService
|
|
|
|
/**
|
|
|
|
* Bounds for the map
|
|
|
|
*/
|
|
|
|
@Prop({ default: null })
|
|
|
|
public fitBounds: LatLngBoundsExpression;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Describes the the zoom control options (see: https://leafletjs.com/reference-1.3.4.html#control-zoom)
|
|
|
|
*/
|
|
|
|
@Prop()
|
|
|
|
public zoomControlOptions: Control.ZoomOptions;
|
|
|
|
|
|
|
|
@Prop()
|
|
|
|
public baseMaps: LayerMap;
|
|
|
|
|
2023-05-02 16:10:32 +00:00
|
|
|
@Ref('zoom') private zoom: ZoomControlComponent;
|
2023-06-01 12:29:56 +00:00
|
|
|
@Ref('draw') private draw: DrawControlComponent;
|
2023-05-02 16:10:32 +00:00
|
|
|
|
2023-06-01 12:29:56 +00:00
|
|
|
// services:
|
2023-03-31 12:54:15 +00:00
|
|
|
mapService = MapService();
|
|
|
|
|
2023-04-12 07:26:45 +00:00
|
|
|
southWest;
|
|
|
|
northEast;
|
|
|
|
|
2023-03-31 12:54:15 +00:00
|
|
|
/**
|
|
|
|
* Informs when initialization is done with map id.
|
|
|
|
*/
|
|
|
|
public onMapInitializedEvent: EventEmitter<string> = new EventEmitter<string>();
|
|
|
|
|
2023-04-12 07:26:45 +00:00
|
|
|
public map!: Map;
|
2023-04-06 16:56:41 +00:00
|
|
|
// protected drawnItems!: FeatureGroup<any>;
|
2023-03-31 12:54:15 +00:00
|
|
|
|
|
|
|
// @Prop({ type: Object })
|
|
|
|
// geolocation: Coverage;
|
|
|
|
|
|
|
|
mounted(): void {
|
|
|
|
this.initMap();
|
2023-05-02 16:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unmounted() {
|
|
|
|
this.map.off('zoomend zoomlevelschange');
|
2023-03-31 12:54:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// @Emit(this.onMapInitializedEvent)
|
|
|
|
protected initMap(): void {
|
2023-06-01 12:29:56 +00:00
|
|
|
// let map: Map = (this.map = this.mapService.getMap(this.mapId));
|
|
|
|
|
2023-03-31 12:54:15 +00:00
|
|
|
let map: Map = (this.map = new Map(this.mapId, this.mapOptions));
|
|
|
|
this.mapService.setMap(this.mapId, map);
|
|
|
|
map.scrollWheelZoom.disable();
|
|
|
|
|
|
|
|
// return this.mapId;
|
|
|
|
// this.$emit("onMapInitializedEvent", this.mapId);
|
|
|
|
this.onMapInitializedEvent.emit(this.mapId);
|
|
|
|
this.addBaseMap();
|
|
|
|
|
2023-04-06 16:56:41 +00:00
|
|
|
const attributionControl = new Attribution().addTo(this.map);
|
|
|
|
attributionControl.setPrefix(false);
|
|
|
|
|
2023-05-02 16:10:32 +00:00
|
|
|
map.on(
|
2023-10-23 13:27:39 +00:00
|
|
|
'Draw.Event.CREATED',
|
2023-05-02 16:10:32 +00:00
|
|
|
function (event) {
|
|
|
|
// drawnItems.clearLayers();
|
|
|
|
// var type = event.type;
|
|
|
|
var layer = event.layer;
|
|
|
|
|
|
|
|
// if (type === "rectancle") {
|
|
|
|
// layer.bindPopup("A popup!" + layer.getBounds().toBBoxString());
|
|
|
|
var bounds = layer.getBounds();
|
|
|
|
this.coverage.x_min = bounds.getSouthWest().lng;
|
|
|
|
this.coverage.y_min = bounds.getSouthWest().lat;
|
|
|
|
// console.log(this.geolocation.xmin);
|
|
|
|
this.coverage.x_max = bounds.getNorthEast().lng;
|
|
|
|
this.coverage.y_max = bounds.getNorthEast().lat;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// drawnItems.addLayer(layer);
|
|
|
|
},
|
|
|
|
this,
|
|
|
|
);
|
|
|
|
|
2023-03-31 12:54:15 +00:00
|
|
|
// Initialise the FeatureGroup to store editable layers
|
2023-04-06 16:56:41 +00:00
|
|
|
// let drawnItems = (this.drawnItems = new FeatureGroup());
|
|
|
|
// map.addLayer(drawnItems);
|
2023-06-01 12:29:56 +00:00
|
|
|
|
|
|
|
this.map.on('zoomend zoomlevelschange', this.zoom.updateDisabled, this.zoom);
|
|
|
|
|
|
|
|
// if (this.fitBounds) {
|
|
|
|
// this.map.fitBounds(this.fitBounds);
|
|
|
|
// }
|
|
|
|
if (this.coverage.x_min && this.coverage.y_min) {
|
|
|
|
this.southWest = toLatLng(this.coverage.y_min, this.coverage.x_min);
|
|
|
|
} else {
|
|
|
|
this.southWest = toLatLng(46.5, 9.9);
|
|
|
|
}
|
|
|
|
if (this.coverage.x_max && this.coverage.y_max) {
|
|
|
|
this.northEast = toLatLng(this.coverage.y_max, this.coverage.x_max);
|
|
|
|
} else {
|
|
|
|
this.northEast = toLatLng(48.9, 16.9);
|
|
|
|
} // this.northEast = toLatLng(48.9, 16.9);
|
|
|
|
const bounds = toLatLngBounds(this.southWest, this.northEast);
|
|
|
|
map.fitBounds(bounds);
|
|
|
|
|
|
|
|
if (this.coverage.x_min && this.coverage.x_max && this.coverage.y_min && this.coverage.y_max) {
|
|
|
|
let _southWest;
|
|
|
|
let _northEast;
|
|
|
|
if (this.coverage.x_min && this.coverage.y_min) {
|
|
|
|
_southWest = toLatLng(this.coverage.y_min, this.coverage.x_min);
|
|
|
|
}
|
|
|
|
if (this.coverage.x_max && this.coverage.y_max) {
|
|
|
|
_northEast = toLatLng(this.coverage.y_max, this.coverage.x_max);
|
|
|
|
}
|
|
|
|
this.draw.drawShape(_southWest, _northEast);
|
|
|
|
}
|
2023-03-31 12:54:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private addBaseMap(layerOptions?: LayerOptions): void {
|
|
|
|
if (this.map) {
|
|
|
|
if (!this.baseMaps || this.baseMaps.size === 0) {
|
|
|
|
// let bmapgrau = tileLayer('https://{s}.wien.gv.at/basemap/bmapgrau/normal/google3857/{z}/{y}/{x}.png', {
|
|
|
|
// subdomains: ['maps', 'maps1', 'maps2', 'maps3', 'maps4'],
|
|
|
|
// attribution: 'Datenquelle: <a href="http://www.basemap.at/">basemap.at</a>',
|
|
|
|
// });
|
2023-04-06 16:56:41 +00:00
|
|
|
let osmGgray = tileLayerWMS('https://ows.terrestris.de/osm-gray/service', {
|
2023-03-31 12:54:15 +00:00
|
|
|
format: 'image/png',
|
|
|
|
attribution: DEFAULT_BASE_LAYER_ATTRIBUTION,
|
|
|
|
layers: 'OSM-WMS',
|
|
|
|
});
|
|
|
|
layerOptions = {
|
|
|
|
label: DEFAULT_BASE_LAYER_NAME,
|
|
|
|
visible: true,
|
|
|
|
layer: osmGgray,
|
|
|
|
};
|
|
|
|
layerOptions.layer.addTo(this.map);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
2023-12-29 14:54:49 +00:00
|
|
|
<style scoped lang="css">
|
|
|
|
/* .leaflet-container {
|
|
|
|
height: 600px;
|
|
|
|
width: 100%;
|
|
|
|
background-color: transparent;
|
|
|
|
outline-offset: 1px;
|
|
|
|
} */
|
2023-03-31 12:54:15 +00:00
|
|
|
.leaflet-container {
|
2023-12-29 14:54:49 +00:00
|
|
|
height: 600px;
|
2023-03-31 12:54:15 +00:00
|
|
|
width: 100%;
|
2023-12-29 14:54:49 +00:00
|
|
|
background: none;
|
2023-03-31 12:54:15 +00:00
|
|
|
}
|
2023-12-29 14:54:49 +00:00
|
|
|
|
2023-05-02 16:10:32 +00:00
|
|
|
.leaflet-pane {
|
|
|
|
z-index: 30;
|
|
|
|
}
|
2023-03-31 12:54:15 +00:00
|
|
|
</style>
|