省-市-区三级联动选择地址 + 地图定位(高德api定位获取位置信息),互相联动显示
一,前言需求:省市区三级联动下拉选择出数据并地图显示位置,地图上选择定位位置三级联动反显出省市区;准备:1.需要全国地址完整(省市区-地区code)的area.json,下载area.js资源。2.地址定位这里用的是高德api故需要申请高德web开发相关申请配置 见这篇。二,实现1.html:这里用的vue<template><!-- 省市区三级联动 --><el-f
·
一,前言
需求: 省市区三级联动 下拉选择出数据 并地图显示位置,地图上选择定位位置 三级联动反显出 省市区;
准备:
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.实现效果截图
选择省市区 或 详细地址-地图显示标记位置
地图选择定位-反显省市区三级联动+详细地址
更多推荐
已为社区贡献5条内容
所有评论(0)