vue 高德地图 地图选点 + 获取当前定位 + 地址逆解析

1、页面效果

在这里插入图片描述

2、注册 key

2.1 登录 高德开放平台

在这里插入图片描述

2.2 创建新应用

在这里插入图片描述

3、代码逻辑

3.1 引入高德地图
npm i @amap/amap-jsapi-loader --save
3.2 初始化地图
<script>
import AMapLoader from '@amap/amap-jsapi-loader'
// 安全密钥
window._AMapSecurityConfig = { securityJsCode: '安全密钥' }

export default {
  methods: {
    initMap() {
      AMapLoader.reset()
      AMapLoader.load({
        key: 'key(Web端)', // 申请好的Web端开发者Key,首次调用 load 时必填
        version: '2.0', // 指定要加载的 JSAPI 的版本,缺少时默认为 1.4.15
        plugins: ['AMap.AutoComplete', 'AMap.Marker', 'AMap.PlaceSearch', 'AMap.Geolocation'] // 需要使用的的插件列表,如比例尺'AMap.Scale'等
      }).then((AMap) => {
        this.aMap = AMap
        // 设置地图容器id
        this.mapEl = new AMap.Map('container', {
          viewMode: '3D', // 是否为3D地图模式
          zoom: 12 // 初始化地图级别
          // center: [116.397428, 39.90923] // 初始化地图中心点位置  默认当前行政区
        })
      })
    }
  }
}
</script>
3.3 设置定位按钮,获取当前位置,地址逆解析
this.geolocation = new AMap.Geolocation({
  enableHighAccuracy: true, // 是否使用高精度定位,默认:true
  timeout: 10000, // 超过10秒后停止定位,默认:5s
  showButton: true, // 显示定位按钮,默认:true
  position: 'RB', // 定位按钮的停靠位置
  offset: [10, 20], // 定位按钮与设置的停靠位置的偏移量,默认:[10, 20]
  showMarker: true, // 定位成功后在定位到的位置显示点标记,默认:true
  panToLocation: true, // 定位成功后将定位到的位置作为地图中心点,默认:true
  zoomToAccuracy: true // 定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
})
this.mapEl.addControl(this.geolocation)
this.geolocation.getCurrentPosition() // 自动获取定位
// 返回定位信息
this.geolocation.on('complete', (res) => {
  console.log('res', res)
})
// 返回定位出错信息
this.geolocation.on('error', (err) => {
  console.log('err', err)
})
// 获取当前位置
getCurrentAddr() {
  this.geolocation.getCurrentPosition((status, result) => {
    // console.log(status, result)
    if (status == 'complete') {
      this.getAddress(result.position.lng, result.position.lat)
      return result.position
    } else {
      this.$message.error('获取定位失败')
    }
  })
},
// 地址逆解析
getAddress(lng, lat) {
  request({
    url: `https://restapi.amap.com/v3/geocode/regeo?location=${lng},${lat}&key=${key(Web服务)}&radius=1000&extensions=all`
    method: 'get'
  }).then((res) => {
    if (res.status == '1') {
      console.log('res', res)
    } else {
      this.$message({ message: res.info, type: 'error' })
    }
  })
},

注意:

地图初始化所用 key 和地址逆解析不同,前者属于 Web端(JS API),后者属于 Web服务

4、源码

4.1 应用
<script>
import Map from './map.vue'
export default {
  components: {
    Map
  },
  data() {
    return {
      show: false,
      addr: {}
    }
  },
  mounted() {},
  methods: {
    open() {
      this.show = true
    },
    confirm(info) {
      this.addr = info
    }
  }
}
</script>
<template>
  <div class="map-point">
    <div class="open">
      <div class="info">
        <p>地址:{{ addr.name }}</p>
        <p>经度:{{ addr.lng }}</p>
        <p>纬度:{{ addr.lat }}</p>
      </div>
      <el-button type="primary" @click="open">打 开</el-button>
    </div>
    <Map :show="show" :info="addr" @cancel="show = false" @confirm="confirm" />
  </div>
</template>
<style lang="scss" scoped>
.map-point {
  .open {
    width: 460px;
    margin: 300px auto;
    .info {
      margin-bottom: 20px;
    }
  }
}
</style>

4.2 map.vue
<script>
import AMapLoader from '@amap/amap-jsapi-loader'
import request from '@/hooks/request.js'
// 安全密钥
window._AMapSecurityConfig = { securityJsCode: '安全密钥' }
export default {
  props: {
    show: {
      type: Boolean,
      default: false
    },
    info: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      visible: false,
      loading: false,
      addrVal: '',
      currentAddr: {},
      addrList: [],
      mapEl: null,
      aMap: null,
      geolocation: null,
      autoComplete: null,
      marker: null
    }
  },
  watch: {
    show(n) {
      this.visible = n
      if (n) {
        this.$nextTick(() => {
          this.initMap()
        })
      }
    },
    info(n) {
      this.currentAddr = n
    }
  },
  methods: {
    initMap() {
      AMapLoader.reset()
      AMapLoader.load({
        key: 'key(Web端)', // 申请好的Web端开发者Key,首次调用 load 时必填
        version: '2.0', // 指定要加载的 JSAPI 的版本,缺少时默认为 1.4.15
        plugins: ['AMap.AutoComplete', 'AMap.Marker', 'AMap.PlaceSearch', 'AMap.Geolocation'] // 需要使用的的插件列表,如比例尺'AMap.Scale'等
      }).then((AMap) => {
        this.aMap = AMap
        // 设置地图容器id
        this.mapEl = new AMap.Map('container', {
          viewMode: '3D', // 是否为3D地图模式
          zoom: 12 // 初始化地图级别
          // center: [116.397428, 39.90923] // 初始化地图中心点位置  默认当前行政区
        })

        // this.geolocation = new AMap.Geolocation({
        //   enableHighAccuracy: true, // 是否使用高精度定位,默认:true
        //   timeout: 10000, // 超过10秒后停止定位,默认:5s
        //   showButton: true, // 显示定位按钮,默认:true
        //   position: 'RB', // 定位按钮的停靠位置
        //   offset: [10, 20], // 定位按钮与设置的停靠位置的偏移量,默认:[10, 20]
        //   showMarker: true, // 定位成功后在定位到的位置显示点标记,默认:true
        //   panToLocation: true, // 定位成功后将定位到的位置作为地图中心点,默认:true
        //   zoomToAccuracy: true // 定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
        // })
        // this.mapEl.addControl(this.geolocation)
        // this.geolocation.getCurrentPosition() // 自动获取定位
        // // 返回定位信息
        // this.geolocation.on('complete', (res) => {
        //   console.log('res', res)
        // })
        // // 返回定位出错信息
        // this.geolocation.on('error', (err) => {
        //   console.log('err', err)
        // })

        this.autoComplete = new AMap.AutoComplete({
          city: '全国'
        })
        if (this.info.lng && this.info.lat) {
          this.addmark(this.currentAddr)
        }
        this.mapEl.on('click', (e) => {
          this.getAddress(e.lnglat.getLng(), e.lnglat.getLat())
        })
      })
    },
    // 获取当前位置
    getCurrentAddr() {
      this.geolocation.getCurrentPosition((status, result) => {
        // console.log(status, result)
        if (status == 'complete') {
          this.getAddress(result.position.lng, result.position.lat)
          return result.position
        } else {
          this.$message.error('获取定位失败')
        }
      })
    },
    // 地址逆解析
    getAddress(lng, lat) {
      request({
        url: `https://restapi.amap.com/v3/geocode/regeo?location=${lng},${lat}&key=${key(Web服务)}&radius=1000&extensions=all`,
        method: 'get'
      }).then((res) => {
        if (res.status == '1') {
          // console.log('res', res)
          this.addmark({ lng, lat, name: res.regeocode.formatted_address })
        } else {
          this.$message({ message: res.info, type: 'error' })
        }
      })
    },
    addmark(info) {
      if (this.marker) this.mapEl.remove(this.marker)
      this.currentAddr = info
      this.marker = new this.aMap.Marker({
        position: new this.aMap.LngLat(info.lng, info.lat),
        title: info.name, // 鼠标滑过点标记时的文字提示
        label: {
          content: info.name // 文本标注的内容
        }
        // zooms: 14 // 点标记显示的层级范围,超过范围不显示。默认值:zooms: [2, 20]
      })
      this.mapEl.add(this.marker)
      this.mapEl.setCenter([info.lng, info.lat], false, 500) // 中心点 是否直接迁移(动画过度) 过渡时间
    },
    // 自定义远程搜索方法
    remoteMethod(e) {
      if (e.trim() != '') {
        this.loading = true
        setTimeout(() => {
          this.autoComplete.search(e, (status, result) => {
            // console.log(status, result)
            this.loading = false
            if (status == 'complete' && result.tips.length) {
              this.addrList = result.tips
            }
          })
        }, 200)
      }
    },
    selectChange(e) {
      if (!e) return
      let info = this.addrList.find((v) => v.name + '_' + v.district == e)
      if (info.location) {
        // 自动适应显示想显示的范围区域
        // this.mapEl.setFitView()
        this.addmark({ ...info.location, name: info.name })
      } else {
        this.$message.warning('该地点经纬度信息缺失')
      }
    },
    cancel() {
      this.visible = false
      this.$emit('cancel', false)
    },
    confirm() {
      if (!this.currentAddr.name) {
        this.$message.warning('请先选择一个地址')
        return
      }
      this.cancel()
      this.$emit('confirm', this.currentAddr)
    }
  }
}
</script>

<template>
  <div class="map_point">
    <el-dialog
      class="dialog"
      title="地图选点"
      v-model="visible"
      top="100px"
      width="80%"
      :draggable="true"
      :show-close="false"
      :close-on-click-modal="false"
      destroy-on-close
    >
      <div class="map-head">
        <el-select
          v-model="addrVal"
          :loading="loading"
          clearable
          remote
          filterable
          reserve-keyword
          placeholder="请输入关键词"
          style="width: 320px"
          :remote-method="remoteMethod"
          @change="selectChange"
        >
          <el-option
            v-for="item in addrList"
            :key="item.id"
            :label="item.name"
            :value="item.name + '_' + item.district"
          >
            <div class="option" style="display: flex; justify-content: space-between">
              <span>{{ item.name }}</span>
              <span style="margin-left: 20px; color: #999; font-size: 12px">
                {{ item.district }}
              </span>
            </div>
          </el-option>
        </el-select>
        <div class="currentAddr">当前选择地址:{{ currentAddr.name }}</div>
      </div>
      <div id="container"></div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="cancel">关 闭</el-button>
          <el-button type="primary" @click="confirm">确 定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<style lang="scss" scoped>
.dialog {
  border-radius: 4px;
  background-color: #ffffff;
  .map-head {
    height: 40px;
    width: 100%;
    display: flex;
    align-items: center;
    .currentAddr {
      margin-left: 32px;
    }
  }

  #container {
    height: 500px;
    width: 100%;
    margin-top: 10px;
  }
}
</style>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值