| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- <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>
- </v-responsive>
- <div class="advice">
- {{ $t("click_on_land_to_go_there") }}
- </div>
- <v-row class="map-shortcuts">
- <v-col v-for="shortcut in shortcuts" :key="shortcut.src" cols="2">
- <div @click="setMapBounds(shortcut.bounds)">
- <nuxt-img
- :src="shortcut.src"
- :alt="shortcut.alt"
- />
- </div>
- </v-col>
- </v-row>
- </LayoutContainer>
- </template>
- <script>
- export default {
- props: {
- structures: {
- type: Array,
- required: false,
- 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,
- 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]] },
- { src: '/images/martinique.png', alt: 'Martinique', bounds: [[14.95, -61.43], [14.28, -60.60]] },
- { src: '/images/mayotte.png', alt: 'Mayotte', bounds: [[-12.51, 44.86], [-13.19, 45.45]] },
- { src: '/images/la_reunion.png', alt: 'La Réunion', bounds: [[-20.65, 54.92], [-21.65, 56.15]] },
- { src: '/images/guyane.png', alt: 'Guyane', bounds: [[6.24, -54.62], [1.87, -50.59]] }
- ],
- zoomRequired: false
- }
- },
- watch: {
- structures () {
- if (this.zoomRequired) {
- this._fitBoundsToMarkers()
- this.zoomRequired = false
- }
- }
- },
- methods: {
- 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.
- },
- resetBounds () {
- this.setMapBounds(this.defaultBounds)
- },
- zoomOnResults () {
- this.zoomRequired = true
- },
- _fitBoundsToMarkers () {
- const coords = this.structures.filter(
- (s) => { return s.latitude && s.longitude }
- ).map(
- (s) => { return [s.latitude, s.longitude] })
- 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)
- }
- }
- }
- </script>
- <style scoped>
- #map {
- height: 100%;
- width: 100%;
- }
- .advice {
- margin: 1rem 0;
- color: #262626;
- font-weight: 750;
- text-align: center;
- font-size: 0.9rem;
- width: 100%;
- }
- .map-shortcuts .col {
- padding: 12px 6px;
- }
- .map-shortcuts img {
- border: solid 1px #000;
- width: 75px;
- height: 75px;
- }
- </style>
|