|
|
@@ -1,35 +1,7 @@
|
|
|
<template>
|
|
|
<LayoutContainer>
|
|
|
<v-responsive :aspect-ratio="1" width="100%">
|
|
|
- <no-ssr>
|
|
|
- <l-map
|
|
|
- id="map"
|
|
|
- ref="vMap"
|
|
|
- :zoom="zoom"
|
|
|
- :center="center"
|
|
|
- :bounds="bounds"
|
|
|
- :options="{scrollWheelZoom: false, zoomSnap: 0.25}"
|
|
|
- @update:bounds="boundsUpdated"
|
|
|
- >
|
|
|
- <l-tile-layer
|
|
|
- url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"
|
|
|
- attribution="© <a href='http://osm.org/copyright'>OpenStreetMap</a> contributors"
|
|
|
- />
|
|
|
- <v-marker-cluster>
|
|
|
- <l-marker
|
|
|
- v-for="structure in structures"
|
|
|
- :key="structure.id"
|
|
|
- :lat-lng="[structure.latitude, structure.longitude]"
|
|
|
- >
|
|
|
- <l-popup>
|
|
|
- <b>{{ structure.name }}</b><br>
|
|
|
- {{ structure.postalCode }} {{ structure.addressCity }}<br>
|
|
|
- <a :href="structure.website" target="_blank">{{ structure.website }}</a>
|
|
|
- </l-popup>
|
|
|
- </l-marker>
|
|
|
- </v-marker-cluster>
|
|
|
- </l-map>
|
|
|
- </no-ssr>
|
|
|
+ <div id="map" />
|
|
|
</v-responsive>
|
|
|
|
|
|
<div class="advice">
|
|
|
@@ -50,6 +22,13 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import 'leaflet/dist/leaflet.css'
|
|
|
+let L
|
|
|
+if (typeof window !== 'undefined') {
|
|
|
+ // only require leaflet on client-side
|
|
|
+ L = require('leaflet')
|
|
|
+}
|
|
|
+
|
|
|
export default {
|
|
|
props: {
|
|
|
structures: {
|
|
|
@@ -59,18 +38,9 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
data () {
|
|
|
- const defaultCenter = [46.71, 1.94]
|
|
|
- const defaultZoom = 5.75
|
|
|
- const defaultBounds = [[51.03, -5.78], [41.2, 9.70]]
|
|
|
-
|
|
|
return {
|
|
|
- defaultCenter,
|
|
|
- defaultZoom,
|
|
|
- defaultBounds,
|
|
|
- center: defaultCenter,
|
|
|
- zoom: defaultZoom,
|
|
|
- bounds: defaultBounds,
|
|
|
- isFirstRendering: true,
|
|
|
+ map: null,
|
|
|
+ defaultBounds: [[51.03, -5.78], [41.2, 9.70]],
|
|
|
shortcuts: [
|
|
|
{ src: '/images/metropole.png', alt: 'Metropole', bounds: [[51.03, -5.78], [41.2, 9.70]] },
|
|
|
{ src: '/images/guadeloupe.png', alt: 'Guadeloupe', bounds: [[16.62, -62.03], [15.74, -60.97]] },
|
|
|
@@ -83,17 +53,61 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
watch: {
|
|
|
- structures () {
|
|
|
+ structures (oldval, newval) {
|
|
|
+ if (oldval !== newval) {
|
|
|
+ this.populateMarkers()
|
|
|
+ }
|
|
|
+
|
|
|
if (this.zoomRequired) {
|
|
|
this._fitBoundsToMarkers()
|
|
|
this.zoomRequired = false
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
+ mounted () {
|
|
|
+ const options = { scrollWheelZoom: false, zoomSnap: 0.25 }
|
|
|
+ const defaultCenter = [46.71, 1.94]
|
|
|
+ const defaultZoom = 5.75
|
|
|
+ const layerSource = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png'
|
|
|
+ const attribution = '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
|
|
+
|
|
|
+ this.map = L.map('map', options)
|
|
|
+ this.map.setView(defaultCenter, defaultZoom)
|
|
|
+ L.tileLayer(layerSource, { attribution }).addTo(this.map)
|
|
|
+
|
|
|
+ this.populateMarkers()
|
|
|
+
|
|
|
+ this.map.on('zoomend moveend', () => {
|
|
|
+ this.$emit('boundsUpdated', this.map.getBounds())
|
|
|
+ })
|
|
|
+ },
|
|
|
+ beforeDestroy () {
|
|
|
+ if (this.map) {
|
|
|
+ this.map.remove()
|
|
|
+ }
|
|
|
+ },
|
|
|
methods: {
|
|
|
+ populateMarkers () {
|
|
|
+ // remove any existant marker layers
|
|
|
+ this.map.eachLayer((layer) => {
|
|
|
+ if (layer instanceof L.MarkerClusterGroup) {
|
|
|
+ this.map.removeLayer(layer)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // populate new layer
|
|
|
+ const clusters = L.markerClusterGroup()
|
|
|
+ for (const s of this.structures) {
|
|
|
+ if (!s.latitude || !s.longitude) { continue }
|
|
|
+
|
|
|
+ const marker = L.marker([s.latitude, s.longitude])
|
|
|
+ marker.bindPopup(`<b>${s.name}</b><br/>${s.postalCode} ${s.addressCity}<br/><a href="${s.website}" target="_blank">${s.website}</a>`)
|
|
|
+ clusters.addLayer(marker)
|
|
|
+ }
|
|
|
+ this.map.addLayer(clusters)
|
|
|
+ },
|
|
|
setMapBounds (bounds) {
|
|
|
- this.bounds = bounds
|
|
|
- this.$refs.vMap.mapObject.fitBounds(bounds) // << without this, the new bounds may not be properly set when the current view overlaps the new bounds.
|
|
|
+ this.map.fitBounds(bounds) // << without this, the new bounds may not be properly set when the current view overlaps the new bounds.
|
|
|
},
|
|
|
resetBounds () {
|
|
|
this.setMapBounds(this.defaultBounds)
|
|
|
@@ -109,15 +123,7 @@ export default {
|
|
|
if (!coords.length > 0) {
|
|
|
return
|
|
|
}
|
|
|
- this.$refs.vMap.mapObject.fitBounds(coords)
|
|
|
- },
|
|
|
- boundsUpdated (newBounds) {
|
|
|
- // do not send and event on first automatic rendering
|
|
|
- if (this.isFirstRendering) {
|
|
|
- this.isFirstRendering = false
|
|
|
- return
|
|
|
- }
|
|
|
- this.$emit('boundsUpdated', newBounds)
|
|
|
+ this.setMapBounds(coords)
|
|
|
}
|
|
|
}
|
|
|
}
|