256 lines
7.9 KiB
Vue
256 lines
7.9 KiB
Vue
<!--
|
||
封装高德地图选址组件
|
||
initMapData: { areacode:[], areacodeNames:[], address: '', lnglat: '' } //areacode 位置、 省市县名称字符串数组、 详细地址, 经纬度(中间,分割)
|
||
@author terrfly
|
||
@site https://www.jeequan.com
|
||
@date 2022/05/07 11:34
|
||
-->
|
||
<template>
|
||
<a-row>
|
||
<a-col :span="isMobile ? 24 : 12">
|
||
<a-form-item label="选址省/市/区" name="areacode">
|
||
<JeepayAreaSelect
|
||
ref="jeepayAreaSelect"
|
||
v-model:value="vdata.mapData.areacode"
|
||
@change="changeAreaCodeFunc"
|
||
:getPopupContainer="(triggerNode) => (triggerNode.parentElement)"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="isMobile ? 24 : 12">
|
||
<a-form-item label="具体位置" name="address">
|
||
<a-input
|
||
id="amap-search-input"
|
||
v-model:value="vdata.mapData.address"
|
||
autoComplete="off"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="isMobile ? 24 : 12">
|
||
<a-form-item label="经纬度" name="lnglat">
|
||
<a-input v-model:value="vdata.mapData.lnglat" autoComplete="off" />
|
||
</a-form-item>
|
||
</a-col>
|
||
</a-row>
|
||
|
||
<a-collapse v-model:activeKey="vdata.showKey" @change="changeMap">
|
||
<a-collapse-panel key="map" header="地图选址">
|
||
<div :id="vdata.mapDivId" :style="{width: '100%', height: isMobile?'300px':'600px'}">MAP</div>
|
||
</a-collapse-panel>
|
||
</a-collapse>
|
||
</template>
|
||
<script lang="ts" setup>
|
||
import { $getMapConfig } from '@/api/manage'
|
||
import { reactive, ref, inject } from 'vue'
|
||
import AMapLoader from '@amap/amap-jsapi-loader'
|
||
|
||
// emit 父组件使用: v-model="val" 进行双向绑定。
|
||
const emit = defineEmits(['update:value', 'change'])
|
||
|
||
// 参数注入: 是否手机端
|
||
let isMobile : any = inject('isMobile')
|
||
|
||
const vdata: any = reactive({
|
||
showKey: 'map',
|
||
mapData: { areacode: [], areacodeNames: [], address: '', lnglat: '' }, //areacode 位置、 省市县、
|
||
|
||
mapDivId: 'mapDIV_' + new Date().getTime()
|
||
|
||
})
|
||
|
||
const jeepayAreaSelect = ref()
|
||
|
||
// 地图对象
|
||
let AMapInstantiate = null as any // 地图实例
|
||
let AMapDefine = null as any // 地图定义,初始成功返回的定义对象, 可以通过 AMapDefine.map等获取
|
||
let AMapDistrictSearch = null as any // 区域搜索插件
|
||
let AMapMarker = null as any //标记点
|
||
let AutoComplete = null as any //自动录入组件
|
||
|
||
/** 初始化 */
|
||
function init(initMapData) {
|
||
// 清空数据
|
||
vdata.mapData.areacode = initMapData.areacode || []
|
||
// vdata.mapData.areacodeNames = initMapData.areacodeNames || []
|
||
vdata.mapData.lnglat = initMapData.lnglat
|
||
vdata.mapData.address = initMapData.address
|
||
|
||
AMapInstantiate = null as any // 地图实例
|
||
AMapDefine = null as any // 地图定义,初始成功返回的定义对象, 可以通过 AMapDefine.map等获取
|
||
AMapDistrictSearch = null as any // 区域搜索插件
|
||
AMapMarker = null as any //标记点
|
||
AutoComplete = null as any //自动录入组件
|
||
|
||
// 获取地图配置参数
|
||
$getMapConfig()
|
||
.then((res) => {
|
||
// @ts-ignore window._AMapSecurityConfig
|
||
window._AMapSecurityConfig = { securityJsCode: res.apiMapWebSecret }
|
||
return AMapLoader.load({
|
||
// 申请好的Web端开发者Key,首次调用 load 时必填
|
||
key: res.apiMapWebKey,
|
||
|
||
// 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
||
version: '2.0',
|
||
|
||
// 同步加载插件
|
||
plugins: [
|
||
'AMap.ToolBar',
|
||
'AMap.Scale',
|
||
'AMap.Marker',
|
||
'AMap.PlaceSearch',
|
||
'AMap.AutoComplete',
|
||
'AMap.Geocoder',
|
||
'AMap.DistrictSearch',
|
||
],
|
||
})
|
||
})
|
||
.then((AMap) => {
|
||
// 定义
|
||
AMapDefine = AMap
|
||
|
||
// 实例化
|
||
AMapInstantiate = new AMapDefine.Map(vdata.mapDivId, {
|
||
viewMode: '3D',
|
||
})
|
||
|
||
AMapInstantiate.addControl(new AMapDefine.ToolBar()) // 工具栏
|
||
AMapInstantiate.addControl(new AMapDefine.Scale()) // 比例尺
|
||
|
||
// geocoder 地理位置查询插件
|
||
var geocoder = new AMap.Geocoder()
|
||
|
||
AMapDistrictSearch = new AMapDefine.DistrictSearch()
|
||
|
||
// 输入提示插件
|
||
AutoComplete = new AMapDefine.AutoComplete({
|
||
input: 'amap-search-input',
|
||
citylimit: true,
|
||
})
|
||
|
||
// 搜索到内容后的回调函数
|
||
AutoComplete.on('select', function (e) {
|
||
let name = e.poi.name // 搜索到的名称
|
||
selectLocationFunc(e.poi.location.lng, e.poi.location.lat, name)
|
||
})
|
||
|
||
// 地图的选中后的回调函数
|
||
AMapInstantiate.on('click', (e) => {
|
||
// 查询省市县、 位置信息
|
||
geocoder.getAddress(
|
||
new AMapDefine.LngLat(e.lnglat.getLng(), e.lnglat.getLat()),
|
||
function (state, result) {
|
||
// 查找失败
|
||
if (state != 'complete') {
|
||
return false
|
||
}
|
||
|
||
// 限制城市搜索
|
||
AutoComplete.setCity(result.regeocode.addressComponent.citycode)
|
||
|
||
// 更改省市县 --> 组件调用change事件
|
||
jeepayAreaSelect.value.changeByAreacode(
|
||
result.regeocode.addressComponent.adcode
|
||
)
|
||
|
||
// 选中的点
|
||
selectLocationFunc(
|
||
e.lnglat.getLng(),
|
||
e.lnglat.getLat(),
|
||
result.regeocode.formattedAddress
|
||
)
|
||
}
|
||
)
|
||
})
|
||
|
||
// 存在数据
|
||
if (initMapData.lnglat) {
|
||
AMapInstantiate.setCenter(
|
||
new AMapDefine.LngLat(
|
||
initMapData.lnglat.split(',')[0],
|
||
initMapData.lnglat.split(',')[1]
|
||
)
|
||
)
|
||
selectLocationFunc(
|
||
initMapData.lnglat.split(',')[0],
|
||
initMapData.lnglat.split(',')[1],
|
||
initMapData.address
|
||
)
|
||
|
||
// 查询省市县、 位置信息 ( 限制城市搜索 )
|
||
geocoder.getAddress(new AMapDefine.LngLat(initMapData.lnglat.split(',')[0], initMapData.lnglat.split(',')[1]), function (state, result) {
|
||
// 查找失败
|
||
if (state != 'complete') {
|
||
return false
|
||
}
|
||
// 限制城市搜索
|
||
AutoComplete.setCity(result.regeocode.addressComponent.citycode)
|
||
})
|
||
|
||
}
|
||
})
|
||
}
|
||
|
||
// 选中某个点的事件: 定位到当前地点
|
||
function selectLocationFunc(lng, lat, name = null) {
|
||
if (name) {
|
||
vdata.mapData.address = name
|
||
}
|
||
|
||
if (!lng || !lat) {
|
||
return false
|
||
}
|
||
|
||
// 更改经纬度坐标
|
||
changeInputLnglat(lng, lat)
|
||
|
||
if (AMapMarker == null) {
|
||
// 创建地图标点中心点
|
||
AMapMarker = new AMapDefine.Marker({
|
||
position: new AMapDefine.LngLat(lng, lat), // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
|
||
})
|
||
AMapInstantiate.add([AMapMarker])
|
||
} else {
|
||
AMapMarker.setPosition(new AMapDefine.LngLat(lng, lat))
|
||
}
|
||
}
|
||
|
||
// 选择省市县的回调函数
|
||
function changeAreaCodeFunc(areacode, val) {
|
||
// 无无变化
|
||
if (vdata.mapData.areacode && vdata.mapData.areacode[2] == val[2]) {
|
||
return
|
||
}
|
||
|
||
// 设置地图的city
|
||
AMapInstantiate.setCity(val[2])
|
||
|
||
// 限制城市搜索
|
||
AutoComplete.setCity(val[2])
|
||
|
||
//
|
||
vdata.mapData.areacode = val
|
||
vdata.mapData.areacodeNames = [
|
||
areacode[0].label,
|
||
areacode[1].label,
|
||
areacode[2].label,
|
||
]
|
||
}
|
||
|
||
// 更改输入框的 经纬度
|
||
function changeInputLnglat(lng, lat) {
|
||
vdata.mapData.lnglat = lng + ',' + lat
|
||
}
|
||
|
||
function getMapData() {
|
||
return vdata.mapData
|
||
}
|
||
// 在移动端收起展开后地图组件未能加载 所以要重新初始化
|
||
const changeMap=(key)=>{
|
||
if(isMobile && key[0] == 'map'){
|
||
init(vdata.mapData)
|
||
}
|
||
}
|
||
defineExpose({ init, getMapData })
|
||
</script>
|
||
|