Я работаю над приложением, в котором есть рестораны на карте (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), это было бы очень полезно. Спасибо.