如何创建GoogleMap标记监听器以打开Vue组件?

时间:2019-06-09 15:44:00

标签: javascript google-maps vue.js google-maps-markers

我正在开发一个应用程序,该应用程序在地图上(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的插件),那将是一个很大的帮助。谢谢。

0 个答案:

没有答案