vue-amap 搜索选点、拖拽选点,地理编码、逆地理编码、IP城市定位、信息窗体

需求 & 图例

标题功能分为2部分的需求:

  1. 【原需求】填写地址:省市区(下拉)+详情(输入),
    【新需求】原需求保持不变,但是增加快捷方式选择地址,a.增加地图搜索选中后 回填地址 b.常用地址/历史地址 列表,选中后 回填地址;
图示说明:
所有图示案例均为代码功能展示用,不考虑美观性。

图示1:
image.png

图示2:
vue-amap 搜索选点、拖拽选点,地理编码、逆地理编码、IP城市定位、信息窗体_第1张图片

  1. 地理编码:地址转为经纬度;逆地理编码:经纬度转为地址;
    【需求】:地图打开中心点默认在ip所在的城市;根据历史GPS数据展示车辆的历史轨迹信息,点击轨迹点展示信息窗体,右侧展示中显示当前车辆的所在的经纬度对应的详细地址;
    图示3:(中心点默认在ip所在的城市)
    vue-amap 搜索选点、拖拽选点,地理编码、逆地理编码、IP城市定位、信息窗体_第2张图片

图示4:(根据GPS数据展示车辆历史轨迹,基于后端返回的数据展示)
vue-amap 搜索选点、拖拽选点,地理编码、逆地理编码、IP城市定位、信息窗体_第3张图片

图示5:(前端模拟数据,展示轨迹,点击展示信息窗体,右侧展示逆地理编码信息)
vue-amap 搜索选点、拖拽选点,地理编码、逆地理编码、IP城市定位、信息窗体_第4张图片

图示6:(根据地址信息转为经纬度,标记在地图上)
vue-amap 搜索选点、拖拽选点,地理编码、逆地理编码、IP城市定位、信息窗体_第5张图片

main.js

import VueAMap from 'vue-amap'; // 命名尽量与AMap做区分

Vue.use(VueAMap); 

VueAMap.initAMapApiLoader({
  key: 'your key',
  plugin: [
    "AMap.Autocomplete",
    "AMap.PlaceSearch",
    "AMap.Scale",
    "AMap.ToolBar",
    "AMap.OverView",
    'AMap.MapType',
    'AMap.PolyEditor',
    'AMap.CircleEditor',
    "AMap.Geolocation",
    "AMap.Geocoder",
    "AMap.CitySearch",
  ],
  v: '1.4.15',
  uiVersion: "1.1"
});
window._AMapSecurityConfig = {
  securityJsCode: 'your security js code',
}
结构以图例1、2 为基础,其他的功能仅以逻辑为主,以说明为准
所有样式代码均省略
省市区下拉是通过访问后端接口,这里需要将地图选点中获得的省市区的名字传给后端,得到下拉需要的codes
常用/历史 选点列表是通过后端接口获得,接口逻辑略,只展示数据结构

map-dialog.vue

template


script

import { GET_CITYS_CODES } from '@/api/xx/index.js';  // 用地图得到的省市区名称换省市区下拉codes

export default {
  props: {
    params: {
      type: Object,
      default: {},
    },
  },
  data() {
    let self = this;
    return {
      activeName: "first",
      amap: {
        zoom: 9,
        center: [0, 0],
        plugin:['ToolBar'],
        marker: [0, 0],
        events: {
          click(e) { self.markerClick(e) }, // 选点点击事件
          dragend(e) { self.dragEnd(e) }, // 选点拖拽事件
        }
      },
      searchOption: {
        city: '',
        citylimit: true
      },
      // dataList本来是后端接口获得,这里不重要,只作数据结构展示
      dataList: [{
        province: "四川省",
        city: "成都市",
        district: "高新区",
        address: "仁和街阿斯顿路250号",
        codes: ['510000', '510100', '510107']
      }],
      obj: {},
      addr: ""
    }
  },
  methods: {
    // 可以放在专门的utils文件中,这里为了方便展示,放在methods里
    // 获取当前ip所在城市
    getCurrentCity() {
      return new Promise((resolve, reject) => {
        let city;
        AMap.plugin('AMap.CitySearch',function(){
          city = new AMap.CitySearch()
        })
        city.getLocalCity(function (status, result) {
          if (status === 'complete' && result.info === 'OK') {
            resolve(result.bounds.oc)
          } else {
            reject('未检测到该地址')
          }
        });
      })
    },
    // 可以放在专门的utils文件中,这里为了方便展示,放在methods里
    // 逆地理编码:经纬度转为地址;
    getPositionByLonLats(lnglat) {
      return new Promise((resolve, reject) => {
        let geocoder;
        AMap.plugin('AMap.Geocoder',function(){
          geocoder = new AMap.Geocoder()
        })
        geocoder.getAddress(lnglat, function (status, result) {
          if (status === 'complete' && result.info === 'OK') {
            resolve(result.regeocode)
          } else {
            reject('未检测到该地址')
          }
        });
      })
    },
    // 可以放在专门的utils文件中,这里为了方便展示,放在methods里
    // 地理编码:地址转为经纬度(与逆地理编码类似,这里不在演示调用)
    getPositionByAddr(addr) {
      return new Promise((resolve, reject) => {
        let geocoder;
        AMap.plugin('AMap.Geocoder',function(){
          geocoder = new AMap.Geocoder()
        })
        geocoder.getLocation(addr, function (status, result) {
          if (status === 'complete' && result.geocodes.length) {
            resolve(result.geocodes[0].location)
          } else {
            reject('未检测到该地址')
          }
        });
      })
    },
    // 弹窗open事件:中心点默认在设在ip所在地址
    setData() {
      this.getCurrentCity().then((res) => {
        this.amap.center = [];
        this.amap.center.push(res.lng, res.lat);
      })
    },
     // 点击搜索列表结果
    // 注意:返回的结果是数组,默认选中第一个,作为点坐标
    async onSearchResult(pois) {
      let self = this;
      await this.getPositionByLonLats([pois[0].lng, pois[0].lat]).then((res) => {
        self.obj = { ...res.addressComponent };
        self.addr = res.formattedAddress;
      }).catch((err) => {
        errorMsg(err);
        return
      })
      self.amap.center = [];
      self.amap.center.push(pois[0].lng, pois[0].lat);
      self.amap.marker = [];
      self.amap.marker.push(pois[0].lng, pois[0].lat);
      self.amap.zoom = 18;
    },
    // 点坐标拖拽结束
    dragEnd(e) {
      let self = this;
      // 
      self.getPositionByLonLats([e.lnglat.lng, e.lnglat.lat]).then((res) => {
        self.obj = { ...res.addressComponent };
        self.addr = res.formattedAddress;
      }).catch((err) => {
        errorMsg(err);
        return
      })
    },
    // 点击点坐标,是否确认选择
    markerClick() {
      let self = this;
      self.$confirm(`是否确认选择【${this.addr}】?`, "确认选择", {
        closeOnClickModal: false,
        cancelButtonClass: "cancel-btn",
        confirmButtonClass: "delete-btn",
      }).then(() => {
        let a = self.obj.province;
        let b = self.obj.city;
        let c = self.obj.district;
        // 将点坐标省市区名称传给后端,获取省市区下拉codes
        // 注意:直辖市,高德不会返回市名称,后端要求,直辖市 省市同名
        GET_CITYS_CODES([a, b?b:a, c]).then((res) => {
          if (res.code === 10000) {
            let info = {
              address: self.obj.township+self.obj.street+self.obj.streetNumber,
              codes: res.result
            }
            // 将确认信息传给父组件
            self.cancel(info);
          }
        });
      })
      .catch(() => {});
    },
    // 常用/历史列表 选择按钮
    selectData(data) {
      let info = {
        address: data.address,
        codes: data.codes
      }
      // 将选择信息传给父组件
      this.cancel(info);
    },

其他功能的

template

// 结构与前面的template类似,这里只保留el-amap

  
  
  
  
  
  
    

{{ info.waybillNo }}

{{ info.plate }}

{{ info.phone }}

{{ info.address }}

script

data() {
  return {
    // 其他类似的略
    info: {}, // 信息窗体
    infoList: [] // 信息窗体集合
  }
},
methods: {
  // 点击坐标点弹出 信息窗体
  markerClick(e) {
    let self = this;
    // 第一次点击 才给所有的信息窗体赋值(为了演示方便放在这里,赋值操作根据实际需求正常操作)
    if (self.infoList.length !== self.pathData.length) {
      for (let i = 0; i < self.pathData.length; i++) {
        let obj = {...self.pathData[i]};
        obj.visible = false
        self.infoList.push(obj);
      }
    // 切换信息窗体手动关闭所有窗体的visible
    } else {
      for (let i = 0; i < self.infoList.length; i++) {
        self.infoList[i].visible = false
      }
    }
    // 清空上一个信息窗体的信息
    self.info = {};
    let arr = [e.target.w.position.lng, e.target.w.position.lat];
    let index = self.pathData.findIndex(i => i.marker.toString() === arr.toString());
    this.$nextTick(() => {
      self.info = self.infoList[index];
      self.$set(self.info, 'visible', true);
    })
  },
}

你可能感兴趣的:(vue-amap 搜索选点、拖拽选点,地理编码、逆地理编码、IP城市定位、信息窗体)