一,前言
需求: 省市區三級聯動 下拉選擇出數據 並地圖顯示位置,地圖上選擇定位位置 三級聯動反顯出 省市區;
準備:
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.實現效果截圖
選擇省市區 或 詳細地址-地圖顯示標記位置
地圖選擇定位-反顯省市區三級聯動+詳細地址