省-市-区三级联动选择地址 + 地图定位(高德api定位获取位置信息),互相联动显示_省级联动api_rain丶子厚的博客-程序员秘密

技术标签: 省市区三级联动  位置定位  高德  javascript  

一,前言

需求: 省市区三级联动 下拉选择出数据 并地图显示位置,地图上选择定位位置 三级联动反显出 省市区;

准备:

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

百度云盘 下载地址  提取码:ufyz (另本已上传csdn资源,设置了几次0c币,但是系统一直自动给改要4-8C币,已弃)

2. 地址定位 这里用的是 高德api 故需要申请高德web开发相关申请配置 见这篇

二,实现

1.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) {
                 // 兼容处理 countyName输入的值中有 XX新区 及 XX区 这种值不确定 不匹配问题
                let countCountyName = ''
                if (countyName.indexOf('新区') !== -1) {
                  countCountyName = countyName.substring(0, countyName.indexOf('新区'))
                } else {
                  countCountyName = countyName
                }
                if (_areaData3[k3].label.indexOf(countCountyName) !== -1) {
                  _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) {
                 // 兼容处理 countyName输入的值中有 XX新区 及 XX区 这种值不确定 不匹配问题
                let countCountyName = ''
                if (countyName.indexOf('新区') !== -1) {
                  countCountyName = countyName.substring(0, countyName.indexOf('新区'))
                } else {
                  countCountyName = countyName
                }
                if (_areaData3[k3].label.indexOf(countCountyName) !== -1) {
                  _county = _areaData3[k3].value
                  break
                }
              }
            }
          }
        }
      }
    }
  }
  addObj = {
    provinceCode: _province,
    cityCode: _city,
    countyCode: _county
  }
  return addObj
}

// String: null => ''
export function stringNullToValue(string) {
  let nowStr = ''
  if (string) {
    nowStr = string
  }
  return nowStr
}

2. 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: '', // 区 县
    street: '', // 街道、乡镇
    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
        }
        // 如果例如: 东莞市-虎门镇 返回信息 district 值为 [], 则 东莞市 区级值  用 township街道值 进行回填
        // console.log('resp.district instanceof Array', resp.district instanceof Array)
        if (resp.district instanceof Array && resp.district.length === 0) {
          nowLocation.district = resp.township
        } else {
          nowLocation.district = resp.district
        }
        nowLocation.street = resp.township
        nowLocation.nowPlace = nowLocation.province + nowLocation.city + nowLocation.district
        nowLocation.lon = longitude
        nowLocation.lat = latitude
        nowLocation.addressDetail = 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)
    }
  })
}

3.这里是 页面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="street">
            <el-input type="text" clearable v-model="objEditData.street" class="w184" @change="detailChange"></el-input>
          </el-form-item>
          <el-form-item label="详细地址" prop="addressDetails">
            <el-input type="text" clearable v-model="objEditData.addressDetails" 
             class="w184" @change="detailChange"></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>

<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: '',
         street: '',
         addressDetails: ''
        },
      }
    },
    mounted() {
      // this.initFunc();
    },
    methods: {
      initFunc() {
        const that = this;
        const province = '广东省'
        const city = '深圳市'
        const county = '南山区'
        const street= '西乡街道'
        const addressDetails = '详细地址'
        // 解析 省市区 编码
        const { provinceCode, cityCode, countyCode } = Utils.areaName2AreaCode([province, city, county]);
        // 如果是编辑 已有 省 市 区 数据进行设置 三级联动显示对应 省市区
        that.objEditData = {
          selectedOptionsStart: [provinceCode, cityCode, countyCode],
          addressDetails
        }
        that.selectArea = {province, city, county, street, addressDetails}
        that.getLngLatFunc(); // 地址转经纬度
      },
      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);
        }
      },
  //  街道/ 乡镇 、详细地址 修改时
    detailChange() {
      this.selectArea.street = this.objEditData.street
      this.selectArea.addressDetails = this.objEditData.addressDetails
      this.getLngLatFunc()
    },
      // 通过 地址 获取 经纬度
      getLngLatFunc() {
        const that = this;
const { province, city, county, street, addressDetails } = that.selectArea;
      const address = Utils.stringNullToValue(province) + Utils.stringNullToValue(city) + Utils.stringNullToValue(county) + Utils.stringNullToValue(street) + Utils.stringNullToValue(addressDetails);
        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, street } = resData.data;
            that.selectArea = {
              province: province,
              city: city,
              county: district,
              street: street,
              addressDetails: addressDetail
            };
            // 解析 省市区 编码
            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);
        this.getLngLatFunc();
      }
    }
  }
</script>

4.实现效果截图

选择省市区 或 详细地址-地图显示标记位置

地图选择定位-反显省市区三级联动+详细地址

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_29101609/article/details/106082395

智能推荐

java byte 查找,终于找到了!有了它你就可以读懂字节码了!_小源 Yuen的博客-程序员秘密

该楼层疑似违规已被系统折叠隐藏此楼查看此楼0x80 ior 将栈顶两int型数值作“按位或”并将结果压入栈顶0x81 lor 将栈顶两long型数值作“按位或”并将结果压入栈顶0x82 ixor 将栈顶两int型数值作“按位异或”并将结果压入栈顶0x83 lxor 将栈顶两long型数值作“按位异或”并将结果压入栈顶0x84 iinc 将指定int型变量增加指定值(i++,i--,i+=2)0x...

ActiveMQConnectionFactory创建ActiveMQConnection之模式应用_yanhongsan的博客-程序员秘密

ActiveMQ中使用了大量的工厂模式和反射模式,下面通过ActiveMQConnectionFactory创建connection来理解一下。       ActiveMQ实现了JMS1.1规范,同样ActiveMQConnectionFactory也是如此,客户端可以通过如下步骤来创建一个Connection:String url = “tcp://localhost:61616”;

HDU 2844_Dilly__dally的博客-程序员秘密

思路:多重背包,dp[i]表示价格总数为i能凑出来的最大价格,比模板多了的唯一一点是查多少数字出现过,枚举一遍dp[i]==i的个数。#include&amp;lt;bits/stdc++.h&amp;gt;using namespace std;#define inf 0x3f3f3f3f#define ll long long#define fo freopen(&quot;in.txt&quot;,&quot;r&quot;,stdin)...

fiddler使用文档_fiddler文档_俩娃的爸爸的博客-程序员秘密

fiddler使用文档.fiddler使用手册一、fiddler介绍二、使用fiddler代理,使手机链接绑定host的无线网络三、抓取移动端app数据包四、抓包 截包伪造提交包五、修改请求的返回数据(mock)六、查看接口响应时间七、模拟2G、3G、4G网络参数八、接口动态转发九、fiddler常用命令一、fiddler介绍简介:Fiddler(中文名称:小提琴)是一个HTTP的调试代理,以代理服务器的方式,监听系统的Http网络数据流动,Fiddle.

SSD实践、原理介绍_【计算机视觉】detection/region/object proposal 方法综述文章_yiyayiya557的博客-程序员秘密

参考文章:https://blog.csdn.net/zzz_cming/article/details/81128460https://blog.csdn.net/zzZ_CMing/article/details/81131101https://blog.csdn.net/zzz_cming/article/details/81131523https://blog.csdn.net/qianqing13579/article/details/82106664https://githu

matlab矩阵按指定顺序排序,根据第二个矩阵(MATLAB)中给出的顺序对矩阵进行排序..._神经现实的博客-程序员秘密

3 个答案:答案 0 :(得分:2)这是我的解决方案:ordermat = [2; 1; 4; 3; 6];bigmat = [1 101 301 402 12 113 584 24 5];%#bigmat = sortrows(bigmat,1);%# keep valid IDs,ord = ordermat( ismember(ordermat,bigmat(:,1)) );ord = gr...

随便推点

SWUST.OJ 493: PostOffice_493: postoffice收藏难度:简单标签:暂无标签题目描述  在一个按照东西和南北方_luckyXiaoDai的博客-程序员秘密

493: PostOffice题目描述  在一个按照东西和南北方向划分成规整街区的城市里,n个居民点散乱地分布在不同的街区中。用x 坐标表示东西向,用y坐标表示南北向。各居民点的位置可以由坐标(x,y)表示。   街区中任意2 点(x1,y1)和(x2,y2)之间的距离可以用数值|x1-x2|+|y1-y2|度量。   居民们希望在城市中选择建立邮局的最佳位置,使n个居民点到邮局的距离总和最小。   任务:给定n 个居民点的位置,编程计算n 个居民点到邮局的距离总和的最小值。输入  第1 行是居民点

[记录]_运行.exe提示缺少MSVCP140_1.dll文件的解决办法_mvscp1 dll_小潘哥201608的博客-程序员秘密

在安装完成PySide2之后,点运行designer.exe,总是提示缺少MSVCP140_1.dll文件,根据网上说法,是要去:https://support.microsoft.com/zh-cn/help/2977003/the-latest-supported-visual-c-downloads下载发行包,安装一下就好。想着自己电脑是64位系统,就安装个64位的得了,但装好后还是报错,进system32去看,dll文件也是有的,奇怪。然后一想,会不会是我Python是32位的,

UIAlertView及UIAlertController在不同系统版本中的自适配_longitachi的博客-程序员秘密

iOS8.0之后,苹果新推出了一种弹框提醒UIAlertController来替代UIAlertView,这也为我们挖了一些坑。比如我就曾与到在8.3系统上,在键盘弹出正在输入的模式下,此时如果点返回按钮的情况下,使用UIAlertView弹框提示用户是否确定返回(为UINavigationController模式下),此时当返回到上个界面之后,键盘会从左至右一闪而过。还有就是比如我们在一

[公告]博客园程序升级成功_weixin_33826609的博客-程序员秘密

博客园程序升级成功!大家如果有什么意见或发现什么Bug请及时与我联系!谢谢!转载于:https://www.cnblogs.com/dudu/archive/2004/07/29/28233.html

QT QLineSeries replace 效率远比 append 高_qlineseries replace_jackylzh的博客-程序员秘密

series-&gt;clear(); QList&lt;QPointF&gt; ps; for (i = 0,p1=buffer1; i &lt; num; i++,p1++) { ...

2020最新常见Java面试题及答案汇总_北京李靓仔爱编程的博客-程序员秘密

一、Java 基础1. JDK 和 JRE 有什么区别?JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境。JRE:Java Runtime Environment 的简称,java 运行环境,为 java 的运行提供了所需环境。具体来说 JDK 其实包含了 JRE,同时还包含了编译 java 源码的编译器 javac,还包含了很多 java 程序调试和分析的工具。简单来说:如果你需要运行 java 程序,只需安装 JRE 就可

推荐文章

热门文章

相关标签