高德地图VUE3

<template>
  <div style="width: 100%;">
    <div id="container" class="map"></div>
    <div class="search-box">
      <!--      <el-select v-model="address" clearable placeholder="请输入关键词" style="width: 400px;" :remote-method="remoteMethod"-->
      <!--                 filterable remote @change="currentSelect" class="one-text" size="default">-->
      <!--        <el-option v-for="(item, index) in areaList" :key="index" :label="item.district + item.name"-->
      <!--                   :value="item.district + item.name">-->
      <!--          <span>{{ item.district }}</span> <span>{{ item.name }}</span>-->
      <!--        </el-option>-->
      <!--      </el-select>-->

      <el-select
          v-model="state.sPoiSearch"
          filterable
          remote
          reserve-keyword
          placeholder="请输入地名"
          :no-data-text="'查询失败,请输入正确地名'"
          :popper-class="'g-poi-search-popper'"
          :remote-method="fnRemoteMethod"
          :loading="state.bPoiSearchLoading"
          @change="fnPoiSearchChange">
        <el-option
            v-for="item in state.aPoiSearchOptions"
            :key="item.value"
            :label="item.label"
            :title="item.label"
            :value="item.value">
        </el-option>
      </el-select>
    </div>
  </div>
</template>

<script setup>
import {defineEmits, defineProps, nextTick, onMounted, reactive, toRefs} from 'vue';
import AMapLoader from "@amap/amap-jsapi-loader";
// 定义子组件向父组件传值/事件
const emit = defineEmits(['addressClick']);
const props = defineProps({
  addressClick: Function,
  lat: {
    type: String,
    default: '',
  },
  lng: {
    // 弹窗内容
    type: String,
    default: '',
  },
})

onMounted(() => {
  //密钥
  window._AMapSecurityConfig = {
    securityJsCode: '102bf56ec19c61303648f21db667ee14',//key密钥
  }
  let lat = props.lat === "" ? 39.566143 : Number(props.lat);
  let lng = props.lng === "" ? 116.209253 : Number(props.lng);
  //北京
  // initMap([lng, lat])
  initMap()

})

const state = reactive({
  geolocation: null,
  map: null,
  placeSearch: null,
  sPoiSearch: '', // 地图搜索关键词
  aPoiSearchOptions: [], // 可选择地图列表
  bPoiSearchLoading: false, // 地图搜索 loading
  autoComplete: null,
  marker: null,
  form: {
    address: '',
    lng: '',
    lat: '',
  },
  areaList: [],
  address: ''
})

/*sPoiSearch: '', // 地图搜索关键词
    aPoiSearchOptions: [], // 可选择地图列表
    bPoiSearchLoading: false, // 地图搜索 loading*/

const {areaList, address, sPoiSearch, aPoiSearchOptions, bPoiSearchLoading} = toRefs(state)

function initMap(arr) {
  console.log("initMap")
  AMapLoader.load({
    key: "6721b02b7cbd15b86d31e8d8d94d0882",//这里放你申请的key
    version: "2.0",
    plugins: ["AMap.ToolBar", "AMap.ControlBar", 'AMap.AutoComplete', 'AMap.PlaceSearch', 'AMap.Geocoder', 'AMap.Marker', 'AMap.Geolocation'],
  }).then((AMap) => {
    state.map = new AMap.Map('container', {
      viewMode: "3D",  //  是否为3D地图模式
      zoom: 15,
      center: arr,
      resizeEnable: true
    });
    // 地图放大缩小插件
    let toolBar = new AMap.ToolBar({
      position: {
        top: '120px',
        right: '51px'
      }
    })
    // 3D地图插件
    let controlBar = new AMap.ControlBar({
      position: {
        top: '20px',
        right: '20px',
      },
    });
    state.geolocation = new AMap.Geolocation({
      enableHighAccuracy: true, // 是否使用高精度定位,默认:true
      //timeout: 10000, // 设置定位超时时间,默认:无穷大
      offset: [10, 20],  // 定位按钮的停靠位置的偏移量
      zoomToAccuracy: true,  //  定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
      position: 'RB' //  定位按钮的排放位置,  RB表示右下
    })


    state.geoCoder = new AMap.Geocoder({
      city: '010', //城市设为北京,默认:“全国”
      radius: 1000 //范围,默认:500
    })

    // 正向地理编码
    state.geocoder = new AMap.Geocoder({

      city: state.address
    })
    //查询
    state.placeSearch = new AMap.PlaceSearch({
      position: {
        top: '20px',
        left: '20px',
      },
      type: "", // 数据类别
      pageSize: 10, // 每页结果数,默认10
      pageIndex: 1, // 请求页码,默认1
      extensions: "base" //返回信息详略,默认为base(基本信息)
    })


    state.autoComplete = new AMap.AutoComplete({city: '全国'});

    state.map.on('click', (e) => { // 点击地图事件
      if (!e && !e.lnglat) {
        return
      }
      console.log("onclick")
      console.log(e)
      state.form.lng = e.lnglat.lng
      state.form.lat = e.lnglat.lat


      removeMarker() // 先删除地图上标记点
      setMapMarker() // 在添加新的标记点
      toGetAddress() //关闭地图,返回父级组件
    })
    state.map.addControl(toolBar);   // 添加右上角的放大缩小
    state.map.addControl(controlBar);   // 添加右上角的放大缩小
    getLocation();//获取当前位置
  }).catch((e) => {
    console.error(e);  //加载错误提示
  }).finally(() => {
    removeMarker()
    setMapMarker()
  })
}

function getLocation() {
  state.geolocation.getCurrentPosition(function (status, result) {
    console.log(status, result)
    if (status === 'complete') {
      onComplete(result)
    } else {
      onError(result)
    }
  });
}

/**
 * 当前位置定位
 * @param data
 */
function onComplete(data) {
  // data是具体的定位信息
  // console.log(data)
  state.form.lng = data.position.lng;
  state.form.lat = data.position.lat;
  removeMarker() // 先删除地图上标记点
  setMapMarker() // 在添加新的标记点

}

function onError(data) {
  // 定位出错
}


/*
* @desc 地图远程搜索方法
* @param query {String} 查询字符
* */
function fnRemoteMethod(query) {
  console.log(query)
  state.placeSearch.search(query, (status, data) => {
    console.log(data)
    // 监听地图搜索查询完成
    if (data.info === 'OK' && data.poiList && data.poiList.pois && data.poiList.pois.length) {
      state.aPoiSearchOptions = data.poiList.pois.map(v => ({
        value: v.id,
        label: v.name,
        location: v.location
      }))
    } else {
      state.aPoiSearchOptions = [];
    }
    state.bPoiSearchLoading = false;

  });
  // if (query !== '' && this.oAddMapPlaceSearch) {
  //   this.bPoiSearchLoading = true;
  //   // 根据关键字获取对应城市里相关的POI信息
  //   this.oAddMapPlaceSearch.search(query);
  // } else {
  //   this.aPoiSearchOptions = [];
  // }
}

/*
* @desc 地图搜索关键词发生变化,并添加标记
* param val {String} 当前选中值
* */
function fnPoiSearchChange(val) {
  console.log(val)
  let oFindMap = state.aPoiSearchOptions.find(v => v.value === val);
  if (oFindMap) {
    state.form.lng = oFindMap.location.lng;
    state.form.lat = oFindMap.location.lat;
    removeMarker()
    setMapMarker()
    // state.map.setCenter( [oFindMap.location.lng, oFindMap.location.lat]);
    // state.map.getAllOverlays('marker').forEach(marker => {
    //   // 移除地图中的 marker 覆盖物
    //   state.map.remove(marker);
    // })
    // // 定位到指定Poi
    // // this.oAddMapMarker.setCenter([oFindMap.location.lng, oFindMap.location.lat]);
    // // this.fnAddMapMarkerHandle([oFindMap.location.lng, oFindMap.location.lat]);
    // state.marker = new AMap.Marker({
    //   map: state.map,
    //   position: [oFindMap.location.lng, oFindMap.location.lat],
    // })
    // // state.map.setFitView()
    // state.map.add(state.marker)
  }


  // let oFindMap = this.aPoiSearchOptions.find(v=> v.value === val);
  // if(oFindMap) {
  //   // 定位到指定Poi
  //   this.oAddMapMarker.setCenter([oFindMap.location.lng, oFindMap.location.lat]);
  //   this.fnAddMapMarkerHandle([oFindMap.location.lng, oFindMap.location.lat]);
  // }
}

function setMapMarker() {
  if (state.form.lng == '' && state.form.lat == '') {
    return
  }
  state.map.setFitView()
  state.marker = new AMap.Marker({
    map: state.map,
    position: [state.form.lng, state.form.lat],
  })
  state.map.setCenter([state.form.lng, state.form.lat]);
  state.map.setFitView()
  state.map.add(state.marker)
}

function removeMarker() {
  if (state.marker) {
    state.map.remove(state.marker)
  }
}

function toGetAddress() {
  let lnglat = [state.form.lng, state.form.lat]
  state.geoCoder.getAddress(lnglat, (status, result) => {
    if (status === 'complete' && result.regeocode) {
      console.log(result)
      state.form.address = result.regeocode.formattedAddress;
      emit('addressClick', state.form);
      //props.addressClick(result, state.form.lng, state.form.lat) // 返回位置信息以及经纬度
    }
  })
}

function remoteMethod(query) {
  if (query !== '') {
    setTimeout(() => {
      state.autoComplete.search(query, (status, result) => {
        state.areaList = result.tips
      })
    }, 500)
  } else {
    state.areaList = []
  }
}

function currentSelect(val) {
  if (!val) {
    return
  }
  toGetCoordinate(val)
}

function toGetCoordinate(address) {
  state.geocoder.getLocation(address, function (status, result) {
    if (status === 'complete' && result.info === 'OK') {
      initMap([result.geocodes[0].location.lng, result.geocodes[0].location.lat])
      state.form.lng = result.geocodes[0].location.lng
      state.form.lat = result.geocodes[0].location.lat
      state.form.address = result.geocodes[0].formattedAddress
    }
  })
  nextTick(function () {
    removeMarker()
    setMapMarker()
  })
}

function fixed(lng, lat) {
  initMap([lng, lat])
  state.form.lng = lng
  state.form.lat = lat
}


// 暴露方法
defineExpose({
  fixed,
  toGetCoordinate
});
</script>


<style scoped lang="scss">
.map {
  width: 100%;
  height: 400px;
}

.search-box {
  position: absolute;
  z-index: 9;
  top: 20px;
  left: 20px;

  ::v-deep(.el-select) {
    width: 320px;
    border-radius: 50px;
    overflow: hidden;

    .el-input__wrapper {
      border-radius: 50px;
    }
  }
}
</style>

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值