(19条消息) vue3 简单封装GoogleMap组件_早上不想起_的博客-CSDN博客
<template>
<div>
<div class="mapBox">
<div class="searchMap">
<div style="width: 100%">
<el-input
v-model="data.searchVal"
placeholder="Please Input"
:prefix-icon="Search"
clearable
@change="searchMap"
/>
</div>
<div v-if="addressParse.address" style="width: 90%; margin: 0 auto; margin-top: 20px">
<el-card class="box-card">
<template #header>
<div class="card-header">
<h3>{{ data.searchVal }}</h3>
</div>
</template>
<div style="color: #bbb; font-size: 12px; margin-bottom: 10px">
{{ addressParse.address }}
</div>
<el-row style="height: 40px" align="middle">
<el-col :span="6">邮编:</el-col>
<el-col :span="14">{{ addressParse.postal_code }}</el-col>
</el-row>
<el-row style="height: 40px" align="middle">
<el-col :span="6">纬度:</el-col>
<el-col :span="14">{{ addressParse.lat }}</el-col>
</el-row>
<el-row style="height: 40px" align="middle">
<el-col :span="6">经度:</el-col>
<el-col :span="14">{{ addressParse.lng }}</el-col>
</el-row>
<el-row style="height: 50px" align="middle" v-if="data.showOk">
<el-col :offset="14" :span="10">
<el-button type="primary" @click="saveAddress">确认选择</el-button>
</el-col>
</el-row>
</el-card>
</div>
</div>
<div id="googleMap" class="mapCont">
<GMapMap ref="mapRef" :center="center" :zoom="gzoom">
<GMapCluster :zoomOnClick="true">
<GMapMarker v-for="(item, index) in markerOptions" :key="index" :position="item.position" />
</GMapCluster>
</GMapMap>
</div>
</div>
</div>
</template>
<script setup props>
import { reactive, onMounted, ref, computed, watch, getCurrentInstance, onUpdated } from 'vue'
import { Search } from '@element-plus/icons-vue'
import settings from '@/settings'
import { ElMessageBox, ElMessage } from 'element-plus'
import axios from 'axios'
const emit = defineEmits(['getLocal'])
const mapRef = ref(null)
const data = reactive({
searchVal: '',
showOk: true
})
const gzoom = ref(15)
const props = defineProps({
lon: {
type: Number,
default() {
return 6.84212
}
},
lat: {
type: Number,
default() {
return 51.093048
}
}
})
const addressParse = reactive({
nation: '',
Province: '',
city: '',
address: '',
postal_code: '',
lat: '',
lng: ''
})
const center = reactive({ lat: 51.093048, lng: 6.84212 })
const mapKey = settings.googleMapKey
const markerOptions = reactive([])
onMounted(() => {
// center.lat = parseFloat(props.lat)
// center.lng = parseFloat(props.lon)
// markerOptions.push({
// position: {
// lat: parseFloat(props.lat),
// lng: parseFloat(props.lon)
// }
// })
// console.log('==================')
// console.log(markerOptions)
center.lat = parseFloat(props.lat)
center.lng = parseFloat(props.lon)
markerOptions.splice(1, 1, { position: { lat: center.lat, lng: center.lng } })
console.log(mapRef.value)
})
onUpdated(() => {
// center.lat = parseFloat(props.lat)
// center.lng = parseFloat(props.lon)
// markerOptions.push({
// position: {
// lat: parseFloat(props.lat),
// lng: parseFloat(props.lon)
// }
// })
// console.log('==================')
// console.log(markerOptions)
markerOptions.slice(1, 1, markerOptions.length - 1, { position: { lat: center.lat, lng: center.lng } })
})
const saveAddress = () => {
console.log('saveAddress', addressParse)
data.showOk = false
emit('getLocal', addressParse)
}
const searchMap = () => {
console.log(mapRef.value)
if (!data.searchVal) {
ElMessage.error('输入地址不能为空')
return
}
addressParse.address = ''
data.showOk = true
reqSearch()
}
const reqSearch = () => {
axios
.get('https://maps.googleapis.com/maps/api/geocode/json?address=' + data.searchVal + '&key=' + mapKey)
.then((res) => {
console.log('res', res)
if (res.data.status == 'OK') {
//中心点
center.lat = res.data.results[0].geometry.location.lat
center.lng = res.data.results[0].geometry.location.lng
markerOptions.splice(1, 1, { position: { lat: center.lat, lng: center.lng } })
var gbounds = new window.google.maps.LatLngBounds()
for (var i = 0; i < markerOptions.length; i++) {
gbounds.extend(markerOptions[i].position)
}
mapRef.value.fitBounds(gbounds)
// gzoom.value = 2
axios
.get(`https://maps.googleapis.com/maps/api/geocode/json?&key=${mapKey}&latlng=${center.lat},${center.lng}`)
.then((res) => {
console.log(res)
if (res.data.status == 'OK') {
addressParse.lat = res.data.results[0].geometry.location.lat
addressParse.lng = res.data.results[0].geometry.location.lng
let sourceData = res.data.results.sort((a, b) => {
return b.address_components.length - a.address_components.length
})
sourceData = sourceData[0].address_components
addressParse.address = res.data.results[0].formatted_address
sourceData.forEach((item) => {
if (item.types[0] == 'country') {
addressParse.nation = item.long_name
}
if (item.types[0] == 'administrative_area_level_1') {
addressParse.Province = item.long_name
}
if (item.types[0] == 'administrative_area_level_2' || item.types[0] == 'locality') {
addressParse.city = item.long_name
}
if (item.types[0] == 'postal_code') {
addressParse.postal_code = item.long_name
}
})
console.log(addressParse)
} else {
ElMessage.error('地址详情查询失败')
}
})
} else {
ElMessage.error('查询失败')
}
})
.catch((err) => {
console.log('err', err)
ElMessage.error('查询失败')
})
}
defineExpose({ addressParse })
</script>
<style lang="scss" scoped>
.mapBox {
width: 100%;
height: 100%;
position: relative;
.searchMap {
width: 30%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.mapCont {
width: 70%;
height: 100%;
position: absolute;
top: 0;
right: 0;
.vue-map-container {
width: 100%;
height: 100%;
}
}
}
</style>