From 9968b1e466db1b936c53325adecfd43ced274e49 Mon Sep 17 00:00:00 2001 From: frankporras Date: Fri, 24 May 2024 13:47:28 +0200 Subject: [PATCH] Publication minimap implemented --- src/components/MapComponent.vue | 40 ----------- src/components/minimap/Minimap.ts | 70 +++++++++++++++++++ src/components/minimap/Minimap.vue | 16 +++++ src/models/dataset.ts | 13 ++++ .../dataset-detail.component.ts | 8 ++- .../dataset-detail.component.vue | 4 +- 6 files changed, 108 insertions(+), 43 deletions(-) delete mode 100644 src/components/MapComponent.vue create mode 100644 src/components/minimap/Minimap.ts create mode 100644 src/components/minimap/Minimap.vue diff --git a/src/components/MapComponent.vue b/src/components/MapComponent.vue deleted file mode 100644 index 5606f84..0000000 --- a/src/components/MapComponent.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/components/minimap/Minimap.ts b/src/components/minimap/Minimap.ts new file mode 100644 index 0000000..8757252 --- /dev/null +++ b/src/components/minimap/Minimap.ts @@ -0,0 +1,70 @@ +import { Component, Prop, Vue } from 'vue-facing-decorator'; +import * as L from 'leaflet'; +import 'leaflet/dist/leaflet.css'; + +@Component({ + name: 'Minimap', +}) +export default class Minimap extends Vue { + @Prop({ type: Array, required: true }) bounds!: L.LatLngBoundsLiteral; + + mounted() { + const map = L.map('map', { + center: [47.71, 13.55], + zoom: 6, + maxZoom: 9, + minZoom: 5, + maxBounds: [ + [45.0, 10.0], // Southwest corner of the bounds + [50.0, 17.0] // Northeast corner of the bounds + ], + maxBoundsViscosity: 1.0 // Ensure the map cannot be dragged outside the bounds + }); + + // const openStreetMapLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + // attribution: '© OpenStreetMap contributors', + // noWrap: true // Prevent tiles from wrapping outside the bounds + // }).addTo(map); + + const basemapAtLayer = L.tileLayer('https://maps{s}.wien.gv.at/basemap/geolandbasemap/normal/google3857/{z}/{y}/{x}.png', { + attribution: 'Datenquelle: basemap.at', + noWrap: true, + subdomains: ['', '1', '2', '3', '4'] + }).addTo(map); + + const esriImageryLayer = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { + attribution: 'Tiles © Esri' + }); + + const esriTopoLayer = L.tileLayer('https://server.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}', { + attribution: 'Tiles © Esri' + }); + + const baseMaps = { + // "OpenStreetMap": openStreetMapLayer, + "basemap.at": basemapAtLayer, + "ESRI Imagery": esriImageryLayer, + "ESRI Topo": esriTopoLayer + }; + + L.control.layers(baseMaps).addTo(map); + + const [southWest, northEast] = this.bounds; + + if (southWest[0] === northEast[0] || southWest[1] === northEast[1]) { + // If y_min and y_max (and x_min and x_max) are equal, generate a circle + const center = [southWest[0], southWest[1]] as L.LatLngExpression; + const radius = 1000; // You can adjust the radius as needed + const circle = L.circle(center, { radius, color: '#336699', weight: 4, opacity: 1 }).addTo(map); + + // Fit the map's view to the circle's bounds + map.fitBounds(circle.getBounds()); + } else { + // Otherwise, generate a rectangle + const rectangle = L.rectangle(this.bounds, { color: '#336699', weight: 2, opacity: 1 }).addTo(map); + + // Fit the map's view to the rectangle's bounds + map.fitBounds(this.bounds); + } + } +} \ No newline at end of file diff --git a/src/components/minimap/Minimap.vue b/src/components/minimap/Minimap.vue new file mode 100644 index 0000000..2563148 --- /dev/null +++ b/src/components/minimap/Minimap.vue @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/src/models/dataset.ts b/src/models/dataset.ts index c3de319..0ec4832 100644 --- a/src/models/dataset.ts +++ b/src/models/dataset.ts @@ -264,6 +264,19 @@ export class DbDataset { return ""; } } + + /* Provides the bounds of the publication for the Leaflet minimap */ + public get Bounds(): L.LatLngBoundsLiteral | string { + if (this.coverage != undefined) { + return [ + [Number(this.coverage.y_min), Number(this.coverage.x_min)], // Southwest corner + [Number(this.coverage.y_max), Number(this.coverage.x_max)] // Northeast corner + ]; + } else { + return ""; + } + } + } type Nullable = T | undefined; diff --git a/src/views/dataset-detail.component/dataset-detail.component.ts b/src/views/dataset-detail.component/dataset-detail.component.ts index 85b06a2..279089e 100644 --- a/src/views/dataset-detail.component/dataset-detail.component.ts +++ b/src/views/dataset-detail.component/dataset-detail.component.ts @@ -1,3 +1,4 @@ +// detail-dataset.component.ts import { Component, Vue, Prop } from "vue-facing-decorator"; import { DbDataset } from "@/models/dataset"; import DatasetService from "../../services/dataset.service"; @@ -9,13 +10,14 @@ import { Suggestion } from "@/models/dataset"; import { VUE_API } from "@/constants"; // import DataMetricsBadge from "data-metrics-badge/dist/data-metrics-badge.js"; // import DataMetricsBadge from "@/components/datacite/DataMetricsBadge.vue"; -import MapComponent from '@/components/MapComponent.vue'; +import Minimap from '@/components/minimap/Minimap.vue'; +import * as L from 'leaflet'; @Component({ name: "DatasetDetailComponent", components: { VsInput, - MapComponent, + Minimap, // DataMetricsBadge, }, }) @@ -174,4 +176,6 @@ export default class DatasetDetailComponent extends Vue { citation += ", Wien"; return citation; } + + } diff --git a/src/views/dataset-detail.component/dataset-detail.component.vue b/src/views/dataset-detail.component/dataset-detail.component.vue index d3894e8..159bd77 100644 --- a/src/views/dataset-detail.component/dataset-detail.component.vue +++ b/src/views/dataset-detail.component/dataset-detail.component.vue @@ -1,3 +1,4 @@ +