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

flatsmap.vue 3.4KB

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