flatisfy/flatisfy/web/js_src/components/flatsmap.vue

125 lines
3.8 KiB
Vue

<template lang="html">
<div class="full">
<v-map :zoom="zoom.defaultZoom" :center="center" :bounds="bounds" :min-zoom="zoom.minZoom" :max-zoom="zoom.maxZoom">
<v-tilelayer :url="tiles.url" :attribution="tiles.attribution"></v-tilelayer>
<v-marker-cluster>
<template v-for="marker in flats">
<v-marker :lat-lng="{ lat: marker.gps[0], lng: marker.gps[1] }" :icon="icons.flat">
<v-popup :content="marker.content"></v-popup>
</v-marker>
</template>
</v-marker-cluster>
<v-marker-cluster>
<template v-for="(place_gps, place_name) in places">
<v-marker :lat-lng="{ lat: place_gps[0], lng: place_gps[1] }" :icon="icons.place">
<v-tooltip :content="place_name"></v-tooltip>
</v-marker>
</template>
</v-marker-cluster>
<template v-for="journey in journeys">
<v-geojson-layer :geojson="journey.geojson" :options="Object.assign({}, defaultGeoJSONOptions, journey.options)"></v-geojson-layer>
</template>
</v-map>
</div>
</template>
<script>
import L from 'leaflet'
// Fix for a bug in Leaflet default icon
// see https://github.com/PaulLeCam/react-leaflet/issues/255#issuecomment-261904061
delete L.Icon.Default.prototype._getIconUrl
L.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')
})
import 'leaflet/dist/leaflet.css'
import 'leaflet.markercluster/dist/MarkerCluster.css'
import 'leaflet.markercluster/dist/MarkerCluster.Default.css'
require('leaflet.icon.glyph')
import { LMap, LTileLayer, LMarker, LTooltip, LPopup, LGeoJSON } from 'vue2-leaflet'
import Vue2LeafletMarkerCluster from 'vue2-leaflet-markercluster'
export default {
data () {
return {
defaultGeoJSONOptions: {
weight: 5,
color: '#000',
opacity: 1,
fillColor: '#e4ce7f',
fillOpacity: 1
},
center: [46.449, 2.210],
zoom: {
defaultZoom: 6,
minZoom: 5,
maxZoom: 17
},
tiles: {
url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
},
icons: {
flat: new L.Icon.Default(),
place: L.icon.glyph({
prefix: 'fa',
glyph: 'clock-o'
})
}
}
},
components: {
'v-map': LMap,
'v-tilelayer': LTileLayer,
'v-marker': LMarker,
'v-marker-cluster': Vue2LeafletMarkerCluster,
'v-tooltip': LTooltip,
'v-popup': LPopup,
'v-geojson-layer': LGeoJSON
},
computed: {
bounds () {
let bounds = []
this.flats.forEach(flat => bounds.push(flat.gps))
Object.keys(this.places).forEach(place => bounds.push(this.places[place]))
if (bounds.length > 0) {
bounds = L.latLngBounds(bounds)
return bounds
} else {
return null
}
}
},
props: ['flats', 'places', 'journeys']
// TODO: Add a switch to display a layer with isochrones
}
</script>
<style lang="css">
.leaflet-popup-content {
max-height: 20vh;
overflow-y: auto;
}
</style>
<style lang="css" scoped>
.full {
width: 100%;
height: 75vh;
background-color: #ddd;
}
#map {
height: 100%;
}
</style>