关于前端:vueamap-搜索选点拖拽选点地理编码逆地理编码IP城市定位信息窗体

54次阅读

共计 6305 个字符,预计需要花费 16 分钟才能阅读完成。

需要 & 图例

题目性能分为 2 局部的需要:

  1. 【原需要】填写地址:省市区(下拉)+ 详情(输出),
    【新需要】原需要放弃不变,然而减少快捷方式抉择地址,a. 减少地图搜索选中后 回填地址 b. 罕用地址 / 历史地址 列表, 选中后 回填地址;

图示阐明:
所有图示案例均为代码性能展现用,不思考好看性。

图示 1:

图示 2:

  1. 天文编码:地址转为经纬度;逆天文编码:经纬度转为地址;
    【需要】:地图关上中心点默认在 ip 所在的城市;依据历史 GPS 数据展现车辆的历史轨迹信息,点击轨迹点展现信息窗体,右侧展现中显示以后车辆的所在的经纬度对应的具体地址;
    图示 3:(中心点默认在 ip 所在的城市)

图示 4:(依据 GPS 数据展现车辆历史轨迹,基于后端返回的数据展现)

图示 5:(前端模仿数据,展现轨迹,点击展现信息窗体,右侧展现逆天文编码信息)

图示 6:(依据地址信息转为经纬度,标记在地图上)

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

<!-- 弹窗相干代码略 -->
<div class="flex">
  <!-- 右边 -->
  <el-amap
    vid="amapContainer"
    :center="amap.center"
    :plugin="amap.plugin"
    :zoom="amap.zoom"
    :zoomEnable="true"
    class="amap" 
  >
    <!-- 搜寻性能 -->
    <el-amap-search-box
      :search-option="searchOption"
      :on-search-result="onSearchResult"
      class="search-box"
      v-if="params.show"
    >
    </el-amap-search-box>
    <!-- 搜寻后失去的点,可拖拽从新选点,点击确认选点 -->
    <el-amap-marker
      :clickable="true"
      :draggable="true"
      :events="amap.events"
      :position="amap.marker"
    />
  </el-amap>
  <!-- 左边 -->
  <el-tabs v-model="activeName" type="border-card">
    <el-tab-pane label="罕用" name="first">
    </el-tab-pane>
    <el-tab-pane label="历史" name="second">
    </el-tab-pane>
    <el-table :data="dataList" border height="100%">
      <el-table-column label="省市区">
        <template slot-scope="scope">
          <span>{{scope.row.province+scope.row.city+scope.row.district}}</span><br>
        </template>
      </el-table-column>
      <el-table-column label="具体地址" prop="address"></el-table-column>
      <el-table-column label="操作" width="60">
        <template slot-scope="scope">
          <span class="blue" @click="selectData(scope.row)"> 抉择 </span>
        </template>
      </el-table-column>
    </el-table>
  </el-tabs>
</div>

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
<el-amap
  vid="amapContainer2"
  :center="amap.center"
  :plugin="amap.plugin"
  :zoom="amap.zoom"
  :zoomEnable="true"
  class="amap" 
>
  <!-- 轨迹 -->
  <el-amap-polyline
    :stroke-weight="6"
    :path="amap.path"
    line-join="round"
    stroke-color="#00BD00"
  />
  <!-- 点 -->
  <el-amap-marker
    v-for="(item, i) in pathData"
    :key="i+Math.random()"
    :clickable="true"
    :position="item.marker"
    :events="{click(e){markerClick(e)} }"
  />
  <!-- 信息窗体 -->
  <el-amap-info-window
    :auto-move="true"
    :close-when-click-map="true"
    :is-custom="true"
    :offset="[-20, -30]"
    :position="info.marker"
    :visible="info.visible"
    v-if="info.visible"
  >
    <div id="info-window">
      <p>{{info.waybillNo}}</p>
      <p>{{info.plate}}</p>
      <p>{{info.phone}}</p>
      <p>{{info.address}}</p>
    </div>
  </el-amap-info-window>
</el-amap>

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);
    })
  },
}

正文完
 0