vue3 简单封装GoogleMap组件

(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>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值