Vue3引用高德地图,进行位置标记获取标记信息

首先安装地图插件

cnpm i @amap/amap-jsapi-loader --save

封装地图子组件

javascript 复制代码
<template>
  <el-dialog
    title="选择地点"
    width="740px"
    class="select-map-dialog"
    v-model="dialogShow"
    :close-on-click-modal="false"
    :modal-orgend-to-body="false"
    :append-to-body="true"
    @close="cancel"
  >
    <div class="amap-box">
      <el-input clearable id="keyword" v-model="tipInput" placeholder="关键词搜索" :prefix-icon="Search"></el-input>
      <div id="custom-amap"></div>
      <div class="info-list" v-if="address">
        <div class="info-item">已选择地点:{{ address }}</div>
        <div class="info-item">地点经纬度:{{ point }}</div>
      </div>
    </div>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="handelSave">确定</el-button>
        <el-button @click="cancel">取消</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, onUnmounted, watch, computed, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import AMapLoader from '@amap/amap-jsapi-loader'
import { Search } from '@element-plus/icons-vue'

const map = ref(null) // 地图对象
const address = ref('') // 地址
const point = ref([]) // 地址对应的经纬度信息

const marker = ref('') // 地图标记
const geocoder = ref('') // 地址解析(正向)

const tipInput = ref('') // 检索关键字
const autoComplete = ref(null)
const placeSearch = ref(null)

const props = defineProps({
  defaultAddress: {
    type: String,
    default: ''
  },
  defaultPoint: {
    type: Array,
    default:[]
  },
  isShow: {
    type: Boolean,
    default: false
  }
})

const emits = defineEmits(['update:isShow', 'getPosition'])
const dialogShow = computed({
  get: () => props.isShow,
  set: (value) => {
    emits('update:isShow', value)
  }
})

watch(
  () => dialogShow,
  async () => {
    // await nextTick()
    // 初始化地图页面
    // initMap()
    setTimeout(()=>{
        initMap()
    },100)
  },
  { deep: true },
  { immediate: true }
)

//   初始化地图页面
const initMap = () => {
  AMapLoader.load({
    key: '你的key', // 申请好的Web端开发者Key,首次调用 load 时必填
    version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    plugins: [
      'AMap.ToolBar',
      'AMap.Scale',
      'AMap.HawkEye',
      'AMap.MapType',
      'AMap.Geolocation',
      'AMap.AutoComplete',
      'AMap.PlaceSearch',
      'AMap.Geocoder'
    ] // 需要使用的的插件列表,如比例尺'AMap.Scale'等
  })
    .then((AMap) => {
      const tempCenter = props.defaultPoint[0]
        ? props.defaultPoint
        : [118.784136, 32.041806]
      map.value = new AMap.Map('custom-amap', {
        // 设置地图容器id
        viewMode: '2D', // 是否为3D地图模式
        zoom: 12, // 初始化地图级别
        showLabel: true, // 是否展示地图文字和 POI 信息。
        resizeEnable: true,
        center: tempCenter // 初始化地图中心点位置
      })
      // 如果父组件传入了有效值 回显一个icon
      if (props.defaultPoint.length > 0) {
        address.value = props.defaultAddress
        point.value = props.defaultPoint
        addMarker()
      }
      // 地图点击事件
      map.value.on('click', clickMapHandler)

      // 引入高德地图的空间绑定使用
      map.value.addControl(new AMap.Scale())
      map.value.addControl(new AMap.ToolBar())
      map.value.addControl(new AMap.HawkEye())
      map.value.addControl(new AMap.MapType())
      map.value.addControl(new AMap.Geolocation())

      // 搜索框自动完成类
      autoComplete.value = new AMap.AutoComplete({
        input: 'keyword' // input 为绑定输入提示功能的input的DOM ID
      })
      // 构造地点查询类
      placeSearch.value = new AMap.PlaceSearch({
        map: map.value
      })
      // 当选中某条搜索记录时触发
      autoComplete.value.on('select', selectHandler)
      // poi覆盖物点击事件
      placeSearch.value.on('markerClick', clickMarkerHandler)
    })
    .catch((e) => {
      console.log(e)
    })
}


const clickMapHandler = (e) => {
  const lng = e.lnglat.lng
  const lat = e.lnglat.lat
  point.value = [lng, lat]
  // 增加点标记
  addMarker()
  // 获取地址
  getAddress()
}

// 增加点标记
const addMarker = () => {
  // 清除其他icon
  if (marker.value) {
    marker.value.setMap(null)
    marker.value = null
  }
  // 重新渲染icon
  marker.value = new AMap.Marker({
    position: point.value, // icon经纬度
    offset: new AMap.Pixel(-13, -30), // icon中心点的偏移量
    icon: new AMap.Icon({
      image:
        '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png',
      size: new AMap.Size(30, 40), // 图标大小
      imageSize: new AMap.Size(30, 40)
    })
  })
  marker.value.setMap(map.value) // 设置icon
}

// 将经纬度转换为地址
const getAddress = () => {
  // 获取地址,这里通过高德 SDK 完成。
  geocoder.value = new AMap.Geocoder()
  // 调用逆解析方法, 个人开发者调用量上限5000(次/日)
  geocoder.value.getAddress(point.value, (status, result) => {
    if (status === 'complete' && result.info === 'OK') {
      if (result && result.regeocode) {
        address.value = result.regeocode.formattedAddress
      }
    }
  })
}
// 当选中某条记录时会触发
const selectHandler = (e) => {
  placeSearch.value.setCity(e.poi.adcode)
  placeSearch.value.search(e.poi.name) // 关键字查询查询
}



// 点击poi覆盖物事件
const clickMarkerHandler = (e) => {
  point.value = [e.data.location.lng, e.data.location.lat]
  getAddress()
}

// 保存当前选择的地址,分发事件
const handelSave = () => {
  if (address.value && point.value.length && point.value.length > 0) {
    const infoObj = {
      address: address.value,
      point: point.value
    }
    tipInput.value = ''
    emits('getPosition', infoObj)
  } else {
    ElMessage.error('请选择地址获取经纬度')
  }
}
const cancel = () => {
  tipInput.value = ''
//   emits('getPosition', {})
}

onUnmounted(() => {
  map.value && map.value.destroy()
})
</script>

<style lang="scss" scoped>
.amap-box {
  padding: 5px 0 0;
  #custom-amap {
    width: 700px;
    height: 400px;
    margin-top: 10px;
    border: 1px solid #ccc;
  }

  .input-with {
    width: 580px;
    z-index: 1;
  }

  .address {
    color: #373737;
  }
  .info-list {
    padding: 5px 5px 0;
    line-height: 24px;
  }
}
</style>

<style lang="scss">
.select-map-dialog {
  .el-dialog__body {
    padding-top: 3px;
    padding-bottom: 3px;
  }
}
.amap-sug-result {
  z-index: 2024;
}
</style>

父组件引用子组件

javascript 复制代码
<amap :isShow="amapVisible" @getPosition="getPosition" />

const getPosition = (infoObj) => {
  amapVisible.value = false
  //获取到位置信息 infoObj
}
相关推荐
前端没钱1 小时前
从 Vue 迈向 React:平滑过渡与关键注意点全解析
前端·vue.js·react.js
顽疲2 小时前
springboot vue 会员收银系统 含源码 开发流程
vue.js·spring boot·后端
羊小猪~~2 小时前
前端入门之VUE--ajax、vuex、router,最后的前端总结
前端·javascript·css·vue.js·vscode·ajax·html5
摸鱼了2 小时前
🚀 从零开始搭建 Vue 3+Vite+TypeScript+Pinia+Vue Router+SCSS+StyleLint+CommitLint+...项目
前端·vue.js
2401_857600953 小时前
基于 SSM 框架 Vue 电脑测评系统:赋能电脑品质鉴定
前端·javascript·vue.js
天之涯上上3 小时前
Pinia 是一个专为 Vue.js 3 设计的状态管理库
前端·javascript·vue.js
CodeChampion5 小时前
60.基于SSM的个人网站的设计与实现(项目 + 论文)
java·vue.js·mysql·spring·elementui·node.js·mybatis
Elena_Lucky_baby5 小时前
实现路由懒加载的方式有哪些?
前端·javascript·vue.js
王解6 小时前
Vue CLI 脚手架创建项目流程详解 (2)
前端·javascript·vue.js
刘大浪6 小时前
vue.js滑动到顶便锁定位置
前端·javascript·vue.js