Как создать GoogleMap Marker Listeners для открытия компонента Vue? - PullRequest
0 голосов
/ 09 июня 2019

Я работаю над приложением, в котором есть рестораны на карте (Google Map API) и в составном списке в стороне.

Я установил прослушиватель, который открывает компонент AddRestaurant щелчком мыши накарта.Что мне не удается сделать, так это настроить прослушиватель для открытия компонента ReadComments, когда пользователь нажимает на маркер.Щелчок не работает, независимо от того, поместил ли я слушатель в компонент GoogleMap (создать карту), или GoogleMarkers (создать маркеры), или MainMap (который импортирует два других).

ИзвинитеЯ не могу поместить код в jsfiddle, поэтому вот код трех компонентов карты:

GoogleMap:

<template>
  <div class="main">
    <div class="google-map" v-bind:id="mapName" ref="mainMap">
    </div>
<!--    Tuto ici : https://itnext.io/new-unnamed-post-8da9cdbf5df3-->
    <template v-if="Boolean(this.google) && Boolean(this.map)">
      <slot :google="google" :map="map"></slot>
    </template>
  </div>
</template>

<script>
  // Utilisation du plugin pour charger de manière asynchrone l'API
  const GoogleMapsAPILoader = require('google-maps-api-loader');

  export default {
    name: 'google-map',
    props: [
      'name',
      'defaultCenter'
    ],
    data: function() {
      return {
        google: null,
        mapName: this.name + "-map",
        userCoord: {},
        markers: [],
        map: null,
        bounds: null,
        infoWindow: null,
        position: {
          lat: null,
          lng: null
        }
      }
    },

    async mounted() {
      const google = await GoogleMapsAPILoader({
        apiKey: 'APIKEY'
      })
      this.google = google
      this.initMap();
      this.addChangeBoundsListener();
      this.openAddRestaurant();
    },
    methods: {
      // Initialise la carte
      initMap() {
        // Pour y faire référence plus facilement
        const element = this.$refs.mainMap
        const options = {
          center: this.defaultCenter,
          zoom: 12,
        }
        this.map = new this.google.maps.Map(element, options);
        this.infoWindow = new this.google.maps.InfoWindow;
        // Emet google et map à MainMap
        this.$emit('map-initialized', {
          google: this.google,
          map: this.map
        })
      },
      addChangeBoundsListener() {
        // Pour utiliser les bounds pour l'affichage des restaurants dans la liste
        google.maps.event.addListener(this.map, 'bounds_changed', (event) => {
          this.$emit('map-bounds-changed')
        })
      },
      openAddRestaurant() {
        // Emet l'event pour ajouter un restaurant au click sur la carte
        google.maps.event.addListener(this.map, 'click', (event) => {
          this.$emit('map-clicked', event);
        })
      },
    }
  };
</script>

<style scoped>
  @media screen and (min-width: 446px) and (max-width: 1200px) {
    .main {
      margin-bottom: 1rem;
    }
  }

  .google-map {
    width: 100%;
    height: 600px;
    margin: 0 auto;
    border: 2px solid #26A65B;
    border-radius: 2rem;
  }
</style>

GoogleMarkers:

<template>
  <div class="google-markers">

  </div>
</template>


<script>
  export default {
    name: 'google-markers',
    props: {
      google: {
        type: Object,
        required: true
      },
      map: {
        type: Object,
        required: true
      },
      marker: {
        type: Object,
        required: true
      }
    },
    data() {
      return {
        mapMarker: null
      }
    },
    mounted() {
      this.mapMarker = new this.google.maps.Marker({
        position: this.marker.position,
        map: this.map,
        marker: this.marker,
        icon: this.getIconUrl(this.marker.type)
      })
    },
    beforeDestroy() {
      this.mapMarker.setMap(null)
    },
    afterDestroy() {
      this.refreshIcon;
    },
    methods: {
      // Dessiner les markers
      getIconUrl(markerType) {
        let icon
        switch (this.marker.type) {
          case 'restaurant':
            icon = 'https://img.icons8.com/ios/50/000000/restaurant-table.png';
            break;
          case 'user':
            icon = 'https://img.icons8.com/color/48/000000/marker.png';
            break;
          default:
            icon = 'https://img.icons8.com/ultraviolet/48/000000/record.png';
            break;
        }
        return icon
      },
      // Ajout Event Listener sur les markers
      openReadComments() {
        // google.maps.event.addListener(this.marker, 'click', (event) => {
        //   console.log('I am clicked');
        // });

        this.marker.addListener('click', function () {
          console.log('clicked');
        });
      },
    },
    computed: {
      refreshIcon() {
        this.mapMarker = new this.google.maps.Marker({
        position: this.marker.position,
        map: this.map,
        marker: this.marker,
        icon: this.getIconUrl(this.marker.type)
      })
      }
    }
  }
</script>


<style scoped>

</style>

MainMap:

<template>
  <google-map
    :center="customCenter"
    :defaultCenter="defaultCenter"
    @map-initialized="initialize"
    @map-bounds-changed="selectVisibleMarker"
    @map-clicked="openAddRestaurant"
  >
    <template slot-scope="{ google, map }">
      <google-markers v-for="marker in markers" :marker="marker" :map="map" :google="google"></google-markers>
      <google-markers v-if="userMarker !== {}" :marker="userMarker" :map="map" :google="google"></google-markers>
    </template>
  </google-map>
</template>

<script>
  import GoogleMap from './GoogleMap'
  import GoogleMarkers from './GoogleMarkers'

  export default {
    components: {
      GoogleMap,
      GoogleMarkers
    },
    data: function() {
      return {
        google: null,
        mapName: this.name + "-map",
        userCoord: {},
        userMarker: {
          type: 'user'
        },
        marker: null,
        map: null,
        bounds: null,
        infoWindow: null,
        position: {
          lat: null,
          lng: null
        },
        defaultCenter: {
          lat: 48.842702,
          lng: 2.328434
        },
        customCenter: {
          lat: null,
          lng: null
        }
      }
    },
    methods: {
      // Vient de GoogleMap
      initialize(data) {
        this.map = data.map
        this.google = data.google

        this.askGeolocation()
      },
      // Demande si l'utilisateur accepte la géolocalisation, et recentre la carte sur sa position si acceptée.
      askGeolocation() {
        if (navigator.geolocation) {
          navigator.geolocation.getCurrentPosition((position) => {
            const pos = {
              lat: position.coords.latitude,
              lng: position.coords.longitude
            };
            this.customCenter = pos
            this.userCoord = pos
            this.userMarker = {
              ...this.userMarker,
              position: pos,
            }
            this.map.setCenter(this.customCenter)
            this.setPlaces(pos);

          }, () => {
            this.handleLocationError(true, this.defaultCenter);
          });
        } else {
          this.handleLocationError(false, this.defaultCenter);
        }
      },
      handleLocationError(browserHasGeolocation, pos) {
        console.log(pos)
        this.map.setCenter(pos)
      },
      // selectVisibleRestaurant dépend du tri et de la zone d'affichage de la carte, et est utilisé par Map et List
      selectVisibleMarker() {
        this.$store.commit('setBoundsValue', this.map.getBounds())
        this.$store.commit('selectVisibleRestaurant')
      },
      // ouvre le composant AddRestaurant avec lat et lng en query
      openAddRestaurant(event) {
        this.$router.push({ path: '/add-restaurant/', query: { lat: event.latLng.lat(), lng: event.latLng.lng() }});
      },
      // Ajout Event Listener sur les markers
      openReadComments() {
        google.maps.event.addListener(this.userMarker, 'click', (event) => {
          console.log('I am clicked');
        });

        // this.marker.addListener('click', function () {
        //   console.log('clicked');
        // });
      },
      // Google Places
      setPlaces(location) {
        this.infowindow = new google.maps.InfoWindow();
        const service = new google.maps.places.PlacesServices(this.map);
        service.nearbySearch({
          location: location,
          radius: 500,
          type: ['restaurant']
        }, callback);
      }
    },
    computed: {
      // Génère les markers
      markers() {
        const markersArray = [
          ...this.$store.getters.getRestaurantList.map((restaurant, index) => {
            return {
              id: index,
              position: {
                lat: parseFloat(restaurant.lat),
                lng: parseFloat(restaurant.long),
              },
              type: 'restaurant'
            }
          })
        ]
        if (this.userMarker !== {}) {
          markersArray.push(this.userMarker)
        }
        return markersArray
      }
    }
  }
</script>

Насколько мне известно, я застрял здесь (но уже пытался поместить этот слушатель в GoogleMap и MainMap. Это метод, который я пытался установить в GoogleMarkers.

openReadComments() {
        // google.maps.event.addListener(this.marker, 'click', (event) => {
        //   console.log('I am clicked');
        // });

        this.marker.addListener('click', function () {
          console.log('clicked');
        });
      },

Я попытался установить прослушиватель на маркер пользователя (поскольку существует только один, поэтому нет проблем с массивом), но он все равно не работает вообще. Слушатель не работает, и в консоли нет сообщений.

Если кто-то знает, как создать таких слушателей (без плагина, доступного для Vuejs), это было бы очень полезно. Спасибо.

...