Flatisfy is your new companion to ease your search of a new housing :)

flatsmap.vue 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. <template lang="html">
  2. <div class="full">
  3. <v-map v-if="bounds" :zoom="zoom.defaultZoom" :bounds="bounds" :min-zoom="zoom.minZoom" :max-zoom="zoom.maxZoom" v-on:click="$emit('select-flat', null)" @update:bounds="bounds = $event">
  4. <v-tilelayer :url="tiles.url" :attribution="tiles.attribution"></v-tilelayer>
  5. <v-marker-cluster>
  6. <template v-for="marker in flats">
  7. <v-marker :lat-lng="{ lat: marker.gps[0], lng: marker.gps[1] }" :icon="icons.flat" v-on:click="$emit('select-flat', marker.flatId)">
  8. <!-- <v-popup :content="marker.content"></v-popup> -->
  9. </v-marker>
  10. </template>
  11. </v-marker-cluster>
  12. <v-marker-cluster>
  13. <template v-for="(place_gps, place_name) in places">
  14. <v-marker :lat-lng="{ lat: place_gps[0], lng: place_gps[1] }" :icon="icons.place">
  15. <v-tooltip :content="place_name"></v-tooltip>
  16. </v-marker>
  17. </template>
  18. </v-marker-cluster>
  19. <template v-for="journey in journeys">
  20. <v-geojson-layer :geojson="journey.geojson" :options="Object.assign({}, defaultGeoJSONOptions, journey.options)"></v-geojson-layer>
  21. </template>
  22. </v-map>
  23. <div v-else>Nothing to display yet</div>
  24. </div>
  25. </template>
  26. <script>
  27. import L from 'leaflet'
  28. // Fix for a bug in Leaflet default icon
  29. // see https://github.com/PaulLeCam/react-leaflet/issues/255#issuecomment-261904061
  30. delete L.Icon.Default.prototype._getIconUrl
  31. L.Icon.Default.mergeOptions({
  32. iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
  33. iconUrl: require('leaflet/dist/images/marker-icon.png'),
  34. shadowUrl: require('leaflet/dist/images/marker-shadow.png')
  35. })
  36. import 'leaflet/dist/leaflet.css'
  37. import 'leaflet.markercluster/dist/MarkerCluster.css'
  38. import 'leaflet.markercluster/dist/MarkerCluster.Default.css'
  39. require('leaflet.icon.glyph')
  40. import { LMap, LTileLayer, LMarker, LTooltip, LPopup, LGeoJson } from 'vue2-leaflet'
  41. import Vue2LeafletMarkerCluster from 'vue2-leaflet-markercluster'
  42. export default {
  43. data () {
  44. return {
  45. defaultGeoJSONOptions: {
  46. weight: 5,
  47. color: '#000',
  48. opacity: 1,
  49. fillColor: '#e4ce7f',
  50. fillOpacity: 1
  51. },
  52. bounds: [[40.91351257612758, -7.580566406250001], [51.65892664880053, 12.0849609375]],
  53. zoom: {
  54. defaultZoom: 6,
  55. minZoom: 5,
  56. maxZoom: 20
  57. },
  58. tiles: {
  59. url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
  60. attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
  61. },
  62. icons: {
  63. flat: new L.Icon.Default(),
  64. place: L.icon.glyph({
  65. prefix: 'fa',
  66. glyph: 'clock-o'
  67. })
  68. }
  69. }
  70. },
  71. components: {
  72. 'v-map': LMap,
  73. 'v-tilelayer': LTileLayer,
  74. 'v-marker': LMarker,
  75. 'v-marker-cluster': Vue2LeafletMarkerCluster,
  76. 'v-tooltip': LTooltip,
  77. 'v-popup': LPopup,
  78. 'v-geojson-layer': LGeoJson
  79. },
  80. watch: {
  81. flats: 'computeBounds',
  82. places: 'computeBounds'
  83. },
  84. methods: {
  85. computeBounds (newData, oldData) {
  86. if (this.flats.length && JSON.stringify(newData) !== JSON.stringify(oldData)) {
  87. const allBounds = []
  88. this.flats.forEach(flat => allBounds.push(flat.gps))
  89. Object.keys(this.places).forEach(place => allBounds.push(this.places[place]))
  90. this.bounds = allBounds.length ? L.latLngBounds(allBounds) : undefined
  91. }
  92. }
  93. },
  94. props: ['flats', 'places', 'journeys']
  95. // TODO: Add a switch to display a layer with isochrones
  96. }
  97. </script>
  98. <style lang="css">
  99. .leaflet-popup-content {
  100. max-height: 20vh;
  101. overflow-y: auto;
  102. }
  103. </style>
  104. <style lang="css" scoped>
  105. .full {
  106. width: 100%;
  107. height: 75vh;
  108. background-color: #ddd;
  109. }
  110. #map {
  111. height: 100%;
  112. }
  113. </style>