Skip to content

Commit

Permalink
MapView: Support multiple locations in one map (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
stefandesu committed Jul 31, 2024
1 parent 411299e commit 1a8396a
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 12 deletions.
48 changes: 40 additions & 8 deletions src/client/components/MapView.vue
Original file line number Diff line number Diff line change
@@ -1,34 +1,66 @@
<script setup>
const props = defineProps({
location: Object,
locations: Array,
})
import "leaflet/dist/leaflet.css"
import { LMap, LTileLayer, LGeoJson } from "@vue-leaflet/vue-leaflet"
import { watch } from "vue"
const geojsonLayerReady = (layer) => {
layer._map?.fitBounds(layer.getBounds())
if (props.location.type === "Point") {
layer._map?.setZoom(15)
const initialBounds = {
_northEast: {
lat: -90,
lng: -180,
},
_southWest: {
lat: 90,
lng: 180,
},
}
let bounds, count
watch(() => props.locations, () => {
bounds = initialBounds
count = 0
}, { immediate: true })
const geojsonLayerReady = (layer, location) => {
count += 1
const layerBounds = layer.getBounds()
// Track all locations and fit the view so that all of them are visible
bounds._northEast.lat = Math.max(bounds._northEast.lat, layerBounds._northEast.lat)
bounds._northEast.lng = Math.max(bounds._northEast.lng, layerBounds._northEast.lng)
bounds._southWest.lat = Math.min(bounds._southWest.lat, layerBounds._southWest.lat)
bounds._southWest.lng = Math.min(bounds._southWest.lng, layerBounds._southWest.lng)
if (count >= props.locations.length) {
layer._map?.fitBounds([
[bounds._northEast.lat, bounds._northEast.lng],
[bounds._southWest.lat, bounds._southWest.lng],
])
// A single point gets zoom level 15 (TODO: 15 seems to far zoomed in.)
if (count === 1 && location.type === "Point") {
layer._map?.setZoom(15)
}
}
}
</script>
<template>
<div style="height: 300px">
<!-- For some reason, we need zoom and center, even though we are providing bounds -->
<!-- Initial zoom and center will be overridden when GeoJSON layer is ready -->
<l-map
:zoom="1"
:center="[47.2, 12]"
:center="[47, 12]"
:use-global-leaflet="false">
<l-tile-layer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
layer-type="base"
name="OpenStreetMap"
attribution="&copy; <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a>" />
<l-geo-json
v-for="(location, index) in locations"
:key="index"
:geojson="location"
@ready="geojsonLayerReady" />
@ready="geojsonLayerReady($event, location)" />
</l-map>
</div>
</template>
6 changes: 2 additions & 4 deletions src/client/views/ItemView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,12 @@ const topConcepts = computed(() => {
</li>
</ul>
</div>
<!-- TODO: Show all locations in one map? Needs test case. -->
<div
v-if="concept?.location?.length"
title="Map">
<MapView
v-for="(location, index) in concept.location"
:key="`${uri}-${index}`"
:location="location" />
:key="`${uri}`"
:locations="Array.isArray(concept.location) ? concept.location : [concept.location]" />
</div>
<div style="margin: 0 0 10px;">
<b>Linked Data:</b>
Expand Down

0 comments on commit 1a8396a

Please sign in to comment.