省-市-區三級聯動選擇地址 + 地圖定位(高德api定位獲取位置信息),互相聯動顯示

一,前言

需求: 省市區三級聯動 下拉選擇出數據 並地圖顯示位置,地圖上選擇定位位置 三級聯動反顯出 省市區;

準備:

1.需要 全國地址完整(省市區-地區code)的 area.json,

百度雲盤 下載地址  提取碼:gsal  (另本已上傳csdn資源,設置了幾次0c幣,但是系統一直自動給改要4-8C幣,已棄)

2. 地址定位 這裏用的是 高德api 故需要申請高德web開發相關申請配置 見這篇

二,實現

1.這裏用的vue

<template>
 <!-- 省市區三級聯動 -->
 <el-form label-width="110px" ref="objEditFrom" :model="objEditData">
   <el-form-item label="發生地點" prop="selectedOptionsStart">
            <el-cascader
              class="w184"
              placeholder="任意搜索地區"
              :options="areaData"
              filterable
              change-on-select
              @change="startAddressChange"
              v-model="objEditData.selectedOptionsStart"
            ></el-cascader>
          </el-form-item>
          <el-form-item label="詳細地址" prop="addressDetails">
            <el-input type="text" clearable v-model="objEditData.addressDetails" 
             class="w184" @change="DetailsChange"></el-input>
          </el-form-item>
</el-from>
 <!-- 地圖 -->
 <div>
   <!-- 地圖容器 -->
   <div id="amap-container" style="width:400px;height: 300px;"></div>
</div>
</template>
<style>
.w184{
  width: 184px!important;
}
</style>

2.utils.js 自用工具類

 @utils/area/index 是標題一 內放置的 area-index.js 資源,自己項目使用自己的資源路徑

/**
 * @param arr 城市地址三級聯動選擇器,選擇出的code 數組
 * @return 返回解析出 省-市-區/縣 的名字 addObj對象
 */
import AreaData from '@/utils/area/index'
export function areaCode2AreaName(arr) {
  // console.log('areaCode2AreaName()-code名轉地址', arr)
  const [provinceCode, cityCode, countyCode] = arr
  let _province, _city, _county
  const _areaData = AreaData
  let addObj = {}
  if (_areaData.length > 0) {
    for (const k in _areaData) {
      if (_areaData[k].value === provinceCode) {
        _province = _areaData[k].label
        const _areaData2 = _areaData[k].children
        for (const k2 in _areaData2) {
          if (_areaData2[k2].value === cityCode) {
            _city = _areaData2[k2].label
            const _areaData3 = _areaData2[k2].children
            for (const k3 in _areaData3) {
              if (_areaData3[k3].value === countyCode) {
                _county = _areaData3[k3].label
                break
              }
            }
          }
        }
      }
    }
  }
  addObj = {
    province: _province,
    city: _city,
    county: _county
  }
  return addObj
}
/**
 * @param arr 城市地址三級聯動選擇器,選擇出的code 數組
 * @return 返回解析出 省-市-區/縣 的code編碼 addObj對象
 */
export function areaName2AreaCode(arr) {
  // console.log('areaName2AreaCode()-地址名轉code', arr)
  const [provinceName, cityName, countyName] = arr
  let _province, _city, _county
  const _areaData = AreaData
  let addObj = {}
  if (_areaData.length > 0) {
    for (const k in _areaData) {
      if (_areaData[k].label === provinceName) {
        _province = _areaData[k].value
        // console.log('areaName2AreaCode()-地址名轉code-_province', _province)
        // 重慶市 500000   ,北京市 110000 ,  上海市 310000,  天津市 120000, 香港特別行政區  810000,  澳門特別行政區 820000
        if (_province === '500000' || _province === '110000' || _province === '310000' || _province === '120000'|| _province === '810000' || _province === '820000') {
          const _areaData2 = _areaData[k].children
          let now_cityName = provinceName
          if (provinceName === '香港特別行政區' || provinceName === '澳門特別行政區') {
            now_cityName = provinceName.replace('特別行政區', '')
          }
          for (const k2 in _areaData2) {
            if (_areaData2[k2].label === now_cityName) {
              _city = _areaData2[k2].value
              const _areaData3 = _areaData2[k2].children
              for (const k3 in _areaData3) {
                if (_areaData3[k3].label === countyName) {
                  _county = _areaData3[k3].value
                  break
                }
              }
            }
          }
        } else {
          const _areaData2 = _areaData[k].children
          for (const k2 in _areaData2) {
            if (_areaData2[k2].label === cityName) {
              _city = _areaData2[k2].value
              const _areaData3 = _areaData2[k2].children
              for (const k3 in _areaData3) {
                if (_areaData3[k3].label === countyName) {
                  _county = _areaData3[k3].value
                  break
                }
              }
            }
          }
        }
      }
    }
  }
  addObj = {
    provinceCode: _province,
    cityCode: _city,
    countyCode: _county
  }
  return addObj
}

3. positionLocation.js 高德地圖定位 經緯度轉地址

/**
 * CopyRight zh
 * 2020/03/31
 * positionLocation.js
 * version : 1.0.0
 */
'use strict'
// import Vue from 'vue'
// import AMap from 'AMap'
// Vue.use(AMap)
import Axios from 'axios'
/**
 * @param address 詳細地址  省-市-區
 * @param callback 回調函數 返回resData
 * @return resData: {
 *    status: true, // 是否成功
      data: null, // 返回數據
      message: null, // 返回提示信息
 *  }
 * */
export function getLngLat(address, callback) {
  console.log('getLngLat()-',address)
  const resData = {
    status: true,
    data: null,
    message: null,
  }
  // 根據地址獲取經緯度
  Axios.get('https://restapi.amap.com/v3/geocode/geo?key=這裏放自己的高德密鑰&&address='+address).then(res=>{
    if(res.status ===200 && res.data.info==='OK'){
      let resp = res.data.geocodes[0]
      // console.error("getLngLat()-resp", resp)
      if(resp){
        resData.data = resp.location.split(',')
        resData.message = '獲取經緯度成功'
        callback(resData)
      }else {
        console.error("不存在該位置信息")
        resData.status = false
        resData.message = '不存在該位置信息'
        callback(resData)
      }
    }else {
      console.error("獲取經緯度信息失敗")
      resData.status = false
      resData.message = '獲取經緯度信息失敗'
      callback(resData)
    }
  })
}

/**
 * @param longitude  經度 英文:longitude  114.044815
 * @param latitude 緯度 英文:latitude   22.687373
 * @param callback 回調函數 返回resData
 * @return resData: {
 *    status: true, // 是否成功
      data: null, // 返回數據
      message: null, // 返回提示信息
 *  }
 * */
export function getLocation(longitude, latitude, callback){
  // const that = this
  const location = longitude + ',' + latitude
  console.log('getLocation()-location',location)
  const resData = {
    status: true,
    data: null,
    message: null,
  }
  const nowLocation = {
    lat: '', // 緯度
    lon: '', // 經度
    province: '', // 省
    city: '', // 市
    district: '', // 區 縣
    nowPlace: '', // 省-市-區
    addressDetail: '' // 詳細地址
  }
  // 根據經緯度獲取地址
  Axios.get('https://restapi.amap.com/v3/geocode/regeo?key=這裏放自己的高德密鑰&location='+location).then(res=>{
    if(res.status === 200 && res.data.info==='OK'){
      let resp= res.data.regeocode.addressComponent
      const addressDetails = res.data.regeocode.formatted_address
      // console.log('getLocation()-resp',resp)
      if(resp){
        nowLocation.province = resp.province
        if(resp.province ==='上海市'||resp.province ==='重慶市'||resp.province ==='天津市'||resp.province ==='北京市'||resp.province ==='香港特別行政區'||resp.province ==='澳門特別行政區'){
          if (resp.province === '香港特別行政區' || resp.province === '澳門特別行政區') {
            nowLocation.city = resp.province.replace('特別行政區', '')
          } else {
            nowLocation.city = resp.province
          }
        } else {
          nowLocation.city = resp.city
        }
        nowLocation.district = resp.district
        nowLocation.nowPlace = nowLocation.province + nowLocation.city + nowLocation.district
        nowLocation.lon = longitude
        nowLocation.lat = latitude
        nowLocation.addressDetail = resp.township + resp.neighborhood.name
        if (resp.district !== false){
          nowLocation.addressDetail = addressDetails.split(resp.district)[1]
        }else if(resp.city !== false){
          nowLocation.addressDetail = addressDetails.split(resp.city)[1]
        }
        resData.data = nowLocation
        resData.message = '獲取位置信息成功'
        callback(resData)
      } else {
        console.error("不存在該位置信息")
        resData.status = false
        resData.message = '不存在該位置信息'
        callback(resData)
      }
    }else {
      console.error("獲取地址信息失敗")
      resData.status = false
      resData.message = '獲取地址信息失敗'
      callback(resData)
    }
  })
}

4.頁面 script

<script>
  import Area from "@/utils/area/index";
  import * as Utils from "@/utils/index";
  import * as LocationAMap from "@/utils/positionLocation/positionLocation";
  export default {
    data() {
      return {
        objEditData: {
          selectedOptionsStart: ["", "", ""], // 省市區 編碼
          addressDetails: null, // 出險地點 詳細地址
          longitude: null,
          latitude: null
        },
        areaData: Area, // 省-市-區三級聯動選擇
        selectArea: {
          province: "",
          city: "",
          county: ""
        },
      }
    },
    mounted() {
      // this.initFunc();
    },
    methods: {
      initFunc() {
        const that = this;
        const province = '廣東省'
        const city = '深圳市'
        const county = '南山區'
        const addressDetails = '詳細地址'
        // 解析 省市區 編碼
        const { provinceCode, cityCode, countyCode } = Utils.areaName2AreaCode([province, city, county]);
        // 如果是編輯 已有 省 市 區 數據進行設置 三級聯動顯示對應 省市區
        that.objEditData = {
          selectedOptionsStart: [provinceCode, cityCode, countyCode],
          addressDetails
        }
        that.selectArea = {province, city, county}
        that.getLngLatFunc(province, city, county); // 地址轉經緯度
      },
      initMap(longitude, latitude,zoom) {
        console.log("initMap()初始化");
        const that = this;
        // const newV = [116.397559, 39.89621]
        //   center: new AMap.LngLat(nowLog, nowLat),
        const nowLog = longitude || 116.397559;
        const nowLat = latitude || 39.89621;
        let zoomdata= zoom?zoom:11
        const mapObj = new AMap.Map("amap-container", {
          center: [nowLog, nowLat],
          zoom: zoomdata // 初始化地圖時顯示的地圖放大等級
        });
        // console.log("initMap()初始化-nowLog", nowLog, nowLat);
        const markerNow = {
          name: "",
          lnglat: [nowLog, nowLat]
        };
        createMarkerFunc(markerNow);
        // 地圖點擊事件
        const showInfoClick = function(e) {
          console.log("showInfoClick()觸發了地圖click事件-e");
          // e.lnglat.getLng(),e.lnglat.getLat()
          const markerItem = {
            name: "",
            lnglat: [e.lnglat.getLng(), e.lnglat.getLat()]
          };
          createMarkerFunc(markerItem);
          setBoundsFunc(markerItem);
          that.getLocationFunc(e.lnglat.getLng(), e.lnglat.getLat());
        };
        // 監聽 地圖點擊事件
        // if (!that.makeInputDisabled) {
        //   mapObj.on("click", showInfoClick);
        // }
        mapObj.on("click", showInfoClick);
        // -------------自定義方法------------------
        // 指定當前地圖顯示範圍,參數bounds爲指定的範圍
        function setBoundsFunc(markerItem) {
          console.log("setBoundsFunc()");
          const start = [
            Number(markerItem.lnglat[0]) - 0.01,
            Number(markerItem.lnglat[1]) - 0.01
          ];
          const end = [
            Number(markerItem.lnglat[0]) + 0.01,
            Number(markerItem.lnglat[1]) + 0.01
          ];
          const mybounds = new AMap.Bounds(start, end);
          mapObj.setBounds(mybounds);
        }
        // 創建Marker方法
        function createMarkerFunc(markerItem) {
          console.log("createMarker()");
          mapObj.clearMap(); // 清除地圖覆蓋物
          // 創建一個 Marker 實例:
          const marker = new AMap.Marker({
            map: mapObj,
            position: new AMap.LngLat(markerItem.lnglat[0], markerItem.lnglat[1])// 經緯度對象,也可以是經緯度構成的一維數組[116.39, 39.9]
          });
          // 將創建的點標記添加到已有的地圖實例:
          mapObj.add(marker);
        }
      },
      // 手動輸入詳細地址 則 地圖渲染 位置
      DetailsChange(e) {
        const address = this.selectArea.province+this.selectArea.city+this.selectArea.county+e
        let that = this;
        LocationAMap.getLngLat(address, function(resData) {
          if (resData.status) {
            console.log("getLngLatFunc()-", resData.data);
            that.LngLat = resData.data;
            that.objEditData.longitude = that.LngLat[0];
            that.objEditData.latitude = that.LngLat[1];
            // 解決 地圖 異步渲染問題
            that.$nextTick(() => {
              that.initMap(that.objEditData.longitude, that.objEditData.latitude,15);
          });
          } else {
            that.$message({
              message: resData.message,
              type: "warning",
              duration: 2000
            });
          }
        });
      },
      // 通過 地址 獲取 經緯度
      getLngLatFunc(province, city, county) {
        const that = this;
        console.log("getLngLatFunc()-", province, city, county);
        const address = province + city + county;
        LocationAMap.getLngLat(address, function(resData) {
          if (resData.status) {
            console.log("getLngLatFunc()-", resData.data);
            that.LngLat = resData.data;
            that.objEditData.longitude = that.LngLat[0];
            that.objEditData.latitude = that.LngLat[1];
            // 解決 地圖 異步渲染問題
            that.$nextTick(() => {
              that.initMap(that.objEditData.longitude, that.objEditData.latitude);
          });
          } else {
            that.$message({
              message: resData.message,
              type: "warning",
              duration: 2000
            });
          }
        });
      },
      // 通過經緯度獲取 地址
      getLocationFunc(longitude, latitude) {
        const that = this;
        // const location = longitude + ',' + latitude
        // console.log('getLocationFunc()-location',location)
        LocationAMap.getLocation(longitude, latitude, function(resData) {
          if (resData.status) {
            const { province, city, district, addressDetail } = resData.data;
            that.selectArea = {
              province: province,
              city: city,
              county: district
            };
            // 解析 省市區 編碼
            const {
              provinceCode,
              cityCode,
              countyCode
            } = Utils.areaName2AreaCode([province, city, district]);
            that.objEditData.selectedOptionsStart = [
              provinceCode,
              cityCode,
              countyCode
            ];
            that.objEditData.addressDetails = addressDetail;
            that.objEditData.longitude = longitude;
            that.objEditData.latitude = latitude;
          } else {
            this.$message({
              message: resData.message,
              type: "warning",
              duration: 2000
            });
          }
        });
      },
      // 三級連選 起運地地址
      startAddressChange(val) {
        const selectArr = val;
        console.log("startAddressChange()-val", val);
        this.selectArea = Utils.areaCode2AreaName(selectArr);
        console.log("areaCode2AreaName()-selectArea", this.selectArea);
        if (this.selectArea.county) {
          const { province, city, county } = this.selectArea;
          this.getLngLatFunc(province, city, county);
        } else if (this.selectArea.city) {
          const { province, city } = this.selectArea;
          this.getLngLatFunc(province, city, "");
        } else if (this.selectArea.province) {
          const { province } = this.selectArea;
          this.getLngLatFunc(province, "", "");
        }
      }
    }
  }
</script>

5.實現效果截圖

選擇省市區 或 詳細地址-地圖顯示標記位置

地圖選擇定位-反顯省市區三級聯動+詳細地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章