第一步:首先申请高德地图key
可以从其他博主那理看如何注册申请
接下来就可以引用组件开发 import AMapLoader from "@amap/amap-jsapi-loader"
我懒得的写白话了 直接代码粘出来 都有注释 不懂问我 我这是弹框里地图封装的子组件
注:谷歌等一些浏览器定位不了只能获取到当前城市
<template>
<div class="aMap">
<div class="left" v-if="dialoglocation === 'update'">
<div class="map-box">
<el-select
size="small"`在这里插入代码片`
v-model="mapAddress"
filterable
clearable`在这里插入代码片`
remote
reserve-keyword
placeholder="请输入地名"
:no-data-text="'查询失败,请输入正确地名'"
:popper-class="'g-poi-search-popper'"
:remote-method="searchKeyWord"
:loading="showsearchResult"
@change="markerResult">
<el-option
v-for="item in poiList"
:key="item.id"
:label="item.name"
:title="item.name"
:value="item.id"/>
</el-select>
<el-button icon="el-icon-search" type="primary" @change="markerResult" size="small" class="mapAddressSearch"/>
</div>
<el-select v-model="radius" size="small" style="width:106px" @change="updateRadius" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
</div>
<div id="container"/>
</div>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader"
window._AMapSecurityConfig = {
securityJsCode: "XXXXXXXXX",//申请key时的安全密钥
}
export default {
name: "MapView",
props: {
signInfoForm: {
type: Object,
default: () => ({}),
},
dialoglocation: {
type: String,
default: 'update',
},
showMap: {
type: Boolean,
default: false,
},
},
data(){
return{
isShowMap: this.showMap,
showsearchResult: false,
poiList: [],
mapModule: null,
map: null,
circle: null,
radius: '300', // 假设当前位置为圆心,1000米为半径
// 搜索输入
mapAddress: this.signInfoForm.name,
autoCompleteComponent: null,
placeSearchComponent: null,
options: [
{
value: '100',
label: '100米'
},
{
value: '200',
label: '200米'
},
{
value: '300',
label: '300米'
},
{
value: '400',
label: '400米'
},
{
value: '500',
label: '500米'
},
{
value: '600',
label: '600米'
},
{
value: '700',
label: '700米'
},
{
value: '800',
label: '800米'
},
{
value: '900',
label: '900米'
},
{
value: '1000',
label: '1000米'
}
],
}
},
watch: {
showMap(val) {
this.isShowMap = val
if(val){
this.initAMap()
}else{
this.map?.destroy()
}
},
signInfoForm(val){
this.mapAddress= val.name
this.radius= val.effectiveRange || '300'
}
},
mounted() {
this.initAMap()
},
unmounted() {
this.map?.destroy()
},
methods: {
initAMap() {
AMapLoader.load({
key: "XXXXXXXX", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [
'AMap.Geocoder',
'AMap.Circle',
'AMap.Geolocation',
'AMap.CitySearch',
'AMap.CircleEditor',
'AMap.PlaceSearch',
'AMap.AutoComplete',
], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
})
.then((AMap) => {
const that = this
// 保存AMap实例
that.mapModule = AMap
that.map = new AMap.Map("container", {
// 设置地图容器id
viewMode: "2D", // 是否为3D地图模式
zoom: 11, // 初始化地图级别
// center: [116.397428, 39.90923], // 初始化地图中心点位置
resizeEnable: true, // 设置地图容器大小变化时自动调整地图大小
})
// 构造定位插件实例
AMap.plugin(['AMap.Geolocation','AMap.AutoComplete','AMap.PlaceSearch'], () => {
let geolocation = new AMap.Geolocation({
enableHighAccuracy: true, // 是否使用高精度定位,默认:true
timeout: that.dialoglocation === 'update' ? 3000 : 0, // 超过5秒后停止定位,默认:无穷大
zoomToAccuracy: true,
})
that.mapSearchInit()
// 获取当前位置具体信息
geolocation.getCurrentPosition((status, result) => {
// 定位成功
if (status == 'complete') {
onComplete(result)
} else {
// 谷歌浏览器等只能获取当前用户所在城市和城市的经纬度
geolocation.getCityInfo((stat, res) => {
if (stat == "complete") {
console.log('城市定位成功', stat, res)
// that.map.setCenter(res.position)
if(that.signInfoForm.name !=='') {
that.echoData(that.signInfoForm)
}
}else {
console.log('未获取定位')
}
})
}
})
// 详情页面高德地图上面定位按钮不展示按钮- 新增地点的时候展示定位按钮
if(that.dialoglocation === 'update'){
that.map.addControl(geolocation)
}else{
that.map.removeControl(geolocation)
}
})
// 定位成功回调函数
function onComplete(data) {
console.log('定位成功', data)
}
that.geoCoder = new AMap.Geocoder()
// 定位失败回调函数
// function onError(data) {
// console.log('定位失败', data)
// }
// 地图点击事件,实现选点
that.map.on('click', (e) => {
console.log(e,'e')
const { lng, lat } = e.lnglat
// 清除之前的标记
that.map.clearMap()
// 在点击的位置添加一个标记
const marker = new that.mapModule.Marker({
map: that.map,
position: [lng, lat],
icon: new that.mapModule.Icon({
size: new that.mapModule.Size(25,25),
image: require(`@/assets/img/marker.png`),
imageSize: new that.mapModule.Size(20, 20),
}),//设置定位图标
offset: new that.mapModule.Pixel(-20,-20), // 设置点标记偏移量
})
marker.setMap(that.map)
that.radiusInit(e.lnglat)
that.geoCoder.getAddress([lng, lat], (status, result) => {
if (status === 'complete' && result.regeocode) {
that.mapAddress = result.regeocode.addressComponent.neighborhood || result.regeocode.formattedAddress
console.log('点击位置信息:', result.regeocode.formattedAddress)
const signInfoForm = {
name: result.regeocode.addressComponent.neighborhood || result.regeocode.formattedAddress,
address:result.regeocode.formattedAddress,
longitude: lng,
latitude: lat,
effectiveRange: this.radius,
}
this.$emit('setSignInfo',signInfoForm)
// id
// let {adcode} = result.regeocode.addressComponent
// let reg = /.+?(省|市|自治区|自治州|县|区)/g
// let provinceId = parseInt(adcode.substr(0, 2) + '0000')
// let cityId = parseInt(adcode.substr(0, 4) + '00')
// let areaId = adcode
// console.log('点击位置的省市区id:', provinceId, cityId, areaId)
}
})
})
})
.catch((e) => {
console.log(e)
})
},
/** 初始化覆盖物 */
radiusInit(data) {
const that = this
that.circle = null
that.circle = new that.mapModule.Circle({
map: that.map,
center: data, // 圆心点坐标
radius: that.radius, // 圆的半径
strokeColor: '#CCA05D', // 边线颜色
strokeOpacity: 1, // 边线透明度
strokeWeight: 1, // 边线宽度
strokeStyle: "dashed", //轮廓线样式
fillColor: '#CCA05D', // 填充颜色
fillOpacity: 0.35, // 填充透明度
})
//圆形 Circle 对象添加到 Map
that.map.add(that.circle)
//根据覆盖物范围调整视野
that.map.setFitView([ that.circle ])
},
// 签到范围修改
updateRadius() {
this.circle.setRadius(this.radius)
const signInfoForm = {
name: this.signInfoForm.name,
address: this.signInfoForm.address,
longitude: this.signInfoForm.longitude,
latitude: this.signInfoForm.latitude,
effectiveRange: this.radius,
}
this.$emit('setSignInfo',signInfoForm)
},
/** 初始化搜索 */
mapSearchInit(){
const _this = this
let autoOptions = {
input: "tipInput",
}
let autoCompleteComponent= new _this.mapModule.Autocomplete(autoOptions)
this.autoCompleteComponent = autoCompleteComponent
// 注册placeSearch组件
this.placeSearchComponent = new _this.mapModule.PlaceSearch()
},
//根据输入内容查询
searchKeyWord(query){
if(query === '') return
let that= this
that.mapAddress = query
that.showsearchResult = true
that.placeSearchComponent.search(query, function (status, result) {
if(status==='complete' && result.info === "OK"){
that.showsearchResult = false
that.poiList = result.poiList.pois
}else{
that.showsearchResult = false
that.poiList = []
that.$message({
message: "没有查到结果",
type: "warning",
})
}
})
},
//选择搜索的内容
markerResult(id){
if(id === '') return
const data =this.poiList.filter(item => item.id === id)[0]
const signInfoForm = {
name: data.name,
address: data.address,
longitude: data.location.lng,
latitude: data.location.lat,
effectiveRange: this.radius,
}
this.echoData(signInfoForm)
},
// 回显数据
echoData(data){
const _this = this
this.showsearchResult = false
this.address = data.name
var marker = new _this.mapModule.Marker({
position: [Number(data.longitude),Number(data.latitude)],
icon: new _this.mapModule.Icon({
size: new _this.mapModule.Size(25,25),
image: require(`@/assets/img/marker.png`),
imageSize: new _this.mapModule.Size(20, 20),
}),//设置定位图标
offset: new _this.mapModule.Pixel(-20,-20), // 设置点标记偏移量
})
this.map.clearMap()// 清除所有覆盖物(点标志) 不能清除 不然覆盖物没了
this.map.add(marker)// 添加点标志
setTimeout(() => {
this.map.setCenter([Number(data.longitude),Number(data.latitude)])
this.map.setZoom(15)
this.radiusInit([Number(data.longitude),Number(data.latitude)])
}, 50)
this.poiList = []
this.$emit('setSignInfo',data)
},
},
}
</script>
<style scoped lang="scss">
.aMap{
display: flex;
flex-direction: row;
position: relative;
.left{
position: absolute;
top: 20px;
left: 24px;
z-index: 99999;
display: flex;
flex-direction: row;
.map-box{
margin-right: 12px;
::v-deep .el-input__inner{
border-radius: 4px 0 0 4px;
border-right: none;
}
::v-deep .el-button{
border-radius: 0 4px 4px 0;
border-left: none;
}
}
}
}
#container {
width: 760px;
height: 380px;
margin: auto;
}
</style>