我有一個功能齊全的自制系統,用于在 Vue3 中處理谷歌地圖。我沒有使用過庫,因為沒有一個庫具有我想要的功能(最終),而且實作我自己似乎相對簡單(直到這個問題為止)。
Map組件如下:
<template>
<div class="map-container">
<div class="google-map" ref="map"></div>
<div>
<slot></slot>
</div>
</div>
</template>
<script>
import { Loader } from '@googlemaps/js-api-loader';
export default {
props: {
latitude: {
type: [String, Number],
default: 0
},
longitude: {
type: [String, Number],
default: 0
},
zoom: {
type: Number,
default: 15
},
},
data(){
return {
map: null,
api: null,
move: null,
}
},
provide: function () {
return {
getMap: this.getMap
}
},
watch: {
latitude(){ this.updateCenter() },
longitude(){ this.updateCenter() }
},
methods: {
getMap(callback){
var self = this;
function checkForMap() {
if (self.map) {
callback(self.map, self.api);
} else {
setTimeout(checkForMap, 50);
}
}
checkForMap();
},
updateCenter(){
let center = new this.api.LatLng(this.latitude, this.longitude);
this.map.panTo(center);
}
},
mounted(){
let self = this
let apiKey = document.getElementById('GOOGLE_MAPS_KEY').value
let loader = new Loader({
apiKey: apiKey,
version: "weekly",
libraries: ["geometry"]
});
loader.load()
.then((google) => {
self.api = google.maps;
self.map = new google.maps.Map(self.$refs.map, {
center: {
lat: parseFloat(self.latitude),
lng: parseFloat(self.longitude)
},
zoom: self.zoom,
disableDefaultUI: true,
});
// Configure the click listener.
self.map.addListener("click", (mapsMouseEvent) => {
self.$emit('click', mapsMouseEvent)
});
// Configure the move listener.
self.map.addListener("bounds_changed", () => {
if(self.move) clearTimeout(self.move);
self.move = setTimeout(() => {
let bounds = self.map.getBounds(true);
let center = self.map.getCenter();
let radius = 100000;
if(bounds && center){
let northEast = bounds.getNorthEast();
radius = self.api.geometry.spherical.computeDistanceBetween(center, northEast);
}
self.$emit('move', {
bounds: bounds,
radius: Math.round(radius),
center: {
latitude: center.lat(),
longitude: center.lng()
}
})
}, 800);
});
})
.catch(e => {});
}
}
</script>
而標記組件如下:
<template>
<div></div>
</template>
<script>
export default {
props: {
latitude: String,
longitude: String,
icon: {
type: String,
default: '/images/pin.png'
}
},
data(){
return {
map: null,
api: null,
marker: null
}
},
inject: ["getMap"],
watch: {
latitude(){ this.updatePosition() },
longitude(){ this.updatePosition() }
},
mounted(){
let self = this
this.getMap(function(map, api){
self.map = map;
self.api = api;
self.marker = new api.Marker({
position: new api.LatLng(self.latitude, self.longitude),
map: map,
icon: self.icon,
});
self.marker.addListener("click", () => {
self.$emit('click', self.marker)
});
})
},
beforeUnmount(){
this.marker.setMap(null);
this.marker = null;
},
methods: {
updatePosition(){
this.marker.setPosition( new this.api.LatLng( parseFloat(this.latitude), parseFloat(this.longitude) ) );
}
}
}
</script>
然后我有一個組件,它使用這些組件來顯示帶有標記的地圖。
<template>
<div>
<div class="admin-site-map">
<google-map :center="center" :zoom="15">
<map-marker v-for="site in sites" :key="site.id"
:latitude="site.latitude"
:longitude="site.longitude"
@click="markerClicked"
/>
</google-map>
</div>
</div>
</template>
<script>
import GoogleMap from '@/components/Core/Maps/GoogleMap';
import Marker from '@/components/Core/Maps/Marker';
export default {
components: { GoogleMap, mapMarker: Marker },
props: ['sites'],
data(){
return {
center: {lat: 0, lng: 0},
}
},
methods: {
markerClicked(value){
console.log('click: ', value)
}
}
}
</script>
當標記(站點)串列發生變化時,我可以看到在beforeUnmount已洗掉的標記上呼叫的方法,但標記并沒有從地圖上消失,我仍然可以單擊標記并接收null在事件。奇怪的是,呼叫this.marker.setVisible(false)確實有效,并且隱藏了標記。我已經堅持了一段時間,所以任何見解或幫助將不勝感激。謝謝!
uj5u.com熱心網友回復:
感謝 User28,我最終找到了解決方案:在標記組件上,marker(這是 Google 標記物件保存到的位置)不應該是反應性屬性。將資料方法更改為
return {
map: null,
api: null
}
修復了問題(即洗掉marker)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/363061.html
標籤:javascript Vue.js 谷歌地图 标记
下一篇:谷歌地圖API確定縮放級別?
