Vue基于高德地图API封装一个地图组件

一、参考资料

高德开放平台 | 高德地图API (amap.com)

二、安装及配置

pnpm i @vuemap/vue-amap --save

man.ts 密钥及安全密钥需要自己到高德地图开放平台控制台获取.

javascript 复制代码
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import vant from 'vant'
import 'vant/lib/index.css'
import VueAMap, { initAMapApiLoader } from '@vuemap/vue-amap'
import '@vuemap/vue-amap/dist/style.css'

import * as echarts from 'echarts'

initAMapApiLoader({
  key: '841d5250cb7f61adda2ee70c1e3abdaf',
  securityJsCode: 'd122cbf5a33de34356661cf0cef1a553', // 新版key需要配合安全密钥使用
  plugins: [
    // 定位空间,用来获取和展示用户主机所在的经纬度位置
    'AMap.Geolocation',
    // 输入提示插件
    'AMap.Autocomplete',
    // POI搜索插件
    'AMap.PlaceSearch',
    // 右下角缩略图插件,比例尺
    'AMap.Scale',
    // 地图鹰眼插件
    'AMap.OverView',
    // 地图工具条
    'AMap.ToolBar',
    // 类别切换空间,实现默认图层与卫星图,实施交通层之间切换的控制
    'AMap.MapType',
    // 编辑 折线多边形
    'AMap.PolyEditor',
    'AMap.CircleEditor',
    // 地图编码
    'AMap.Geocoder'
  ]
})

const app = createApp(App)
//全局挂载echarts
app.config.globalProperties.$echarts = echarts
app.use(router)
app.use(ElementPlus)
app.use(VueAMap)
app.use(vant)
app.mount('#app')
三、源码分享

1、map.vue

javascript 复制代码
<template>
  <el-dialog v-model="showMapDialog">
    <template #default>
      <div id="container">
        <AmapSelect v-model="locationData" @callback="getMapInfo" />
      </div>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import { ref, nextTick, defineEmits } from 'vue'
// import { ElMessage } from 'element-plus';
import AmapSelect from './AmapSelect.vue'

const props = defineProps({
  title: {
    type: String,
    default: '选择位置'
  },

  center: {
    type: Array,
    default: () => [115.846381, 28.659961]
  }
})

const locationData:any = ref([])
const showMapDialog = ref(false)
const emit = defineEmits(['submit'])

function getMapInfo(info: any) {
  // console.log(info,'info'); 可拿到点击的地址 以及经纬度  可用于做回显等其他操作
  // debugger
  emit('submit', {
    address: info.address,
    lnglat: info.lnglat
  })
}

const openForm = () => {
  showMapDialog.value = true
  nextTick(() => {
    locationData.value=props.center;
  })
}

//提交

// const okModal = async () => {}

//导出方法

defineExpose({
  openForm
})
</script>

<style lang="scss" scoped>
#container {
  height: 400px;
}

.el-dialog__body {
  padding: 0 !important;
}
</style>

2、AmapSelect.vue

javascript 复制代码
<template>
  <el-amap :zoom="zoom" @init="init">
    <el-amap-search-box
      :visible="visible"
      @select="selectChange"
      @choose="handleChange"
      placeholder="请输入"
    />

  </el-amap>
</template>

<script>
export default {
  name: 'AmapSelect',

  emits: ['callback'],

  props: {
    visible: {
      type: Boolean,
      default: true
    },

    modelValue: {
      type: Array,
      default: []
    }
  },

  data() {
    return {
      zoom: 12,
      map: null,
      geocoder: new AMap.Geocoder({}),
      activeAddress: null,
    }
  },

  watch: {
    modelValue: {
      handler(val, oldVal) {
        if (val) {
          // let lnglat = val[1].split(',')

          this.onClickMap({
            lnglat: { lng: val[0], lat: val[1] }
          })
        }
      },

      deep: true
    }
  },

  mounted() {},

  methods: {
    init(map) {
      this.map = map

      map.on('click', this.onClickMap.bind(this))
    },

    selectChange({ poi }) {
      if (poi.location) {
        let { lng, lat } = poi.location

        this.onClickMap(
          {
            lnglat: { lng, lat }
          },

          () => {
            this.map.setCenter([lng, lat])
          }
        )
      }
    },

    handleChange(e) {
      console.log('handleChange: ', e)
    }, 
    
    
    // 点击地图
    onClickMap(e, callback) {
      let lnglat = [e.lnglat.lng, e.lnglat.lat]

      var infoWindow = new AMap.InfoWindow({
        offset: new AMap.Pixel(0, 0)
      })

      this.geocoder.getAddress(lnglat, (status, result) => {
        if (status === 'complete' && result.info === 'OK') {
          // result为对应的地理位置详细信息

          var province = result.regeocode.addressComponent.province //省

          var city = result.regeocode.addressComponent.city //市

          var district = result.regeocode.addressComponent.district //县区

          var township = result.regeocode.addressComponent.township //镇、街道

          var region = province + city + district + township //返回所属区域

          let addressName = result.regeocode.formattedAddress.replace(
            region,
            ''
          )

          let address = ''

          if (!addressName) {
            address = region

            addressName = region
          } else {
            address = result.regeocode.formattedAddress
          }

          let obj = {
            lnglat: lnglat.toString(),

            address: address,

            addressName: addressName
          }

          infoWindow.setContent(this.createdInfoWindowContent(obj))

          infoWindow.open(this.map, lnglat) // 更新数据

          callback && callback()
        }
      })

      this.map.setCenter(lnglat)
    }, 
    // 窗口信息
    createdInfoWindowContent(data) {
      var infoWindowContent =
        '<style>.btn {display: inline-block; font-weight: 400; text-align: center; white-space: nowrap; vertical-align: middle;' +
        '-webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; border: 1px solid transparent;' +
        'transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;' +
        'background-color: transparent; background-image: none; color: #25A5F7; border-color: #25A5F7; padding: .25rem .5rem; line-height: 1.5;' +
        'border-radius: 1rem;  -webkit-appearance: button; cursor:pointer;}</style>' +
        '<div className="custom-infowindow input-card">' +
        '<label  class="input-item-text">' +
        data.addressName +
        '</label>' +
        '<div class="input-item">' +
        '<div class="input-item-prepend">' +
        '<span style="color:grey">' +
        data.address +
        '</span>' +
        '</div>' +
        '</div>' + // 为 infowindow 添加自定义事件
        '<input id="lnglat2container" type="button" class="btn" value="选择地址" onclick="setLngLat()"/>' +
        '</div>'
        // debugger;

      window.setLngLat = () => {
        this.$emit('update:modelValue', [data.address, data.lnglat])
        this.$emit('callback', data)
      }

      return infoWindowContent
    }
  }
}
</script>

<style lang="scss" scoped>


</style>
四、效果展示

点击窗口信息的选择地址可拿到点击位置的信息然后再做后续操作!!!主要还是参考高德地图API的官方文档.

相关推荐
西猫雷婶2 小时前
python学opencv|读取图像(十九)使用cv2.rectangle()绘制矩形
开发语言·python·opencv
liuxin334455663 小时前
学籍管理系统:实现教育管理现代化
java·开发语言·前端·数据库·安全
码农W3 小时前
QT--静态插件、动态插件
开发语言·qt
ke_wu3 小时前
结构型设计模式
开发语言·设计模式·组合模式·简单工厂模式·工厂方法模式·抽象工厂模式·装饰器模式
code04号3 小时前
python脚本:批量提取excel数据
开发语言·python·excel
小王爱吃月亮糖3 小时前
C++的23种设计模式
开发语言·c++·qt·算法·设计模式·ecmascript
hakesashou4 小时前
python如何打乱list
开发语言·python
LCG元4 小时前
Vue.js组件开发-使用vue-pdf显示PDF
vue.js
网络风云4 小时前
【魅力golang】之-反射
开发语言·后端·golang
Want5954 小时前
Java圣诞树
开发语言·python·信息可视化