账号注册
首先得成为高德地图开发者,也就是说你的拥有一个账号,当然有公司账号最好,没有就暂时自己先注册一个。
注册好后,点开控制台,右上角创建一个新应用,选好你需要的环境,vue的话估计基本都是web端吧,然后就可以看到你的开发需要的key了
高德地图插件安装
首先说明,这里示例项目使用vue-cli3脚手架,不熟悉的可以先去看看vue-cli3创建项目相关。
npm安装vue-amap
npm install vue-amap --save
页面引入与组件配置
我这里的项目因为多个地方都会用的地图,所以将地图这一块抽离出来做一个单独的组件,并且是全局组件,方便页面引用
创建全局组件AMap
创建全局地图组件文件AMap.vue以及全局组件配置文件globalComponents.js
项目目录结构如图所示
main.js页面引入vue-amap以及globalComponents.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import globalComponents from './assets/commonJs/globalComponents' //全局组件配置文件
import VueAMap from 'vue-amap'; // 高德地图
import {AMapKey} from './assets/commonJs/constDatas'//AMapKey是高德地图开发key,我这里放到了一个专门的文件管理,你也可以不必这样做。
Vue.use(VueAMap) //插件使用声明
Vue.use(globalComponents) //插件使用声明
//下面是vue-amap初始化,请将AMapKey换成你自己的key
VueAMap.initAMapApiLoader({
key:AMapKey,
plugin: ['AMap.Autocomplete', 'AMap.PlaceSearch', 'AMap.Scale', 'AMap.OverView', 'AMap.ToolBar', 'AMap.MapType', 'AMap.PolyEditor', 'AMap.CircleEditor', 'AMap.Geolocation', ],
v: '1.4.4'
})
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
配置AMap为全局组件
在globalComponents.js文件中
import AMap from '../../globalComponents/AMap/AMap'; //高德地图组件
export default {
install(Vue) {
Vue.component('AMap', AMap)
}
};
AMap页面实现
**这里强调一下,想要使用好vue-amap,首先得在页面引入AMap地图标签创建地图实例,后面才可以使用相应的API,有些小伙伴可能并不需要展示地图,只是想使用某个API,比如根据经纬度获取地址,所以在main.js中配置好后就迫不及待的去相应的页面来这么一段
AMap.plugin(‘AMap.Geocoder’, ()=> {
let geocoder = new AMap.Geocoder({
// city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
city:citycode
})
geocoder.getAddress([lng,lat], (status, result)=> {
…
})
**
然后你看到可能就是下面这种
还有你可能直接在页面引入,比如这样 import AMap from ‘vue-amap’,然后你很可能看到下面这样的报错。
其他废话不多说了,总之必须得先在html部分用标签创建好实例,其他API才可以使用。废话不多说,上代码,先看html部分
<template>
<div class="amapBox" :style="{height}">
<el-amap class="amap-box" :vid="'amap-vue'" :plugin="plugin" :center="mapCenter" :events="events" ref="map">
<el-amap-marker
vid="component-marker"
:position="markPosition"
:icon="require('../../assets/images/mapMark.png')"
:draggable="true"
:raiseOnDrag="true"
:events="markEvents"
></el-amap-marker>
</el-amap>
</div>
</template>
el-amap即vue-amap创建实例的标签,class不用说,vid照写就好,是地图组件id,另外plugin是地图插件配置,center是地图的中心位置,events是事件
el-amap-marker是地图标记标签,其中position是标签位置,icon是标记图标,可以使用网络图片或者本地图片,本地图片请使用require引入,draggable表示是否可以拖动标记,events是事件
<!--js部分-->
<script>
export default {
name: 'AMap',
//考虑到动态需求,允许默认中心点和地图高度从父组件传递来,如果不传递,则使用默认值
props:{
center:{
type:Array,
default:()=>{return [106.61994874,26.64158513]}
},
height:{
type:String,
default:'6rem'
}
},
data() {
return {
mapCenter: [],//地图中心坐标数组,因为可能会从父组件传递,所以初始为空,将会在created生命周期中赋值
loaded: false,
/*events是包含地图事件的对象,init是地图初始化时触发,moveeend地图拖动时触发,click点击地图触发,zoomchange地图缩放级别更改后触发*/
events: {
init:this.mapInit,
'moveend': this.moveend,
'zoomchange': this.zoomchange,
'click': this.mapClick
},
markEvents:{//标记事件
click:this.markClick, //标记点击触发
dragend:this.markDragend //标记拖动触发
},
plugin: [ //插件
{
pName: 'Geolocation', //定位插件
events: {
init:this.getGolocationInit //定位初始化函数
}
},'Autocomplete','PlaceSearch','Scale','OverView','PolyEditor','ToolBar',
],
markPosition:[106.61994874,26.64158513],//标记物位置
cityInfo:{},//当前城市信息
}
},
methods: {
// 地图初始化函数
mapInit(o){
// console.log(o.getCenter())
// console.log(this.$refs.map.$$getInstance())
o.getCity(result => {
this.cityInfo=result
this.$emit('getInitCityInfo',result)//获取初始化城市信息并传递给父组件
})
},
//点图点击事件
async mapClick(e){
// console.log(e)
let {lng,lat} =e.lnglat
this.markPosition=[lng,lat]
this.$emit('getMapClickLngLat',[lng,lat])//获取点击地图点经纬度并传递给父组件
let addressInfo=await this.getAddressFromLngLat(lng,lat)
this.$emit('getAddressInfo',addressInfo)//点击地图获取地址并传递给父组件
},
//定位初始化
getGolocationInit(o){
o.getCurrentPosition((status, result) => {
if (result && result.position) {
// console.log(result)
let {position,addressComponent,formattedAddress}=result
let {lng,lat}=position
this.mapCenter = [lng, lat]
this.markPosition = [lng, lat]
this.loaded = true;
this.$nextTick();
this.$emit('getGolocationInitAddressInfo',{ //获取定位信息并传递给父组件
addressComponent,
formattedAddress,
lng,
lat
})
}
});
},
//地图移动
moveend(){
},
//地图比例改变
zoomchange(){
},
markClick(){
// alert('xxx')
},
//根据经纬度获取地址
getAddressFromLngLat(lng,lat){
let {cityInfo}=this
let {citycode}=cityInfo
return new Promise((resolve,reject)=>{
AMap.plugin('AMap.Geocoder', ()=> {
let geocoder = new AMap.Geocoder({
// city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
city:citycode
})
geocoder.getAddress([lng,lat], (status, result)=> {
// console.log(status,result)
if (status === 'complete' && result.info === 'OK') {
// result为对应的地理位置详细信息
let {addressComponent,formattedAddress}=result.regeocode
let {province,city,district,township}=addressComponent
resolve({
formattedAddress,
province,
city,
district,
township
})
}
})
})
})
},
//标记点拖动结束
async markDragend(e){
let {lng,lat} =e.lnglat
let addressInfo=await this.getAddressFromLngLat(lng,lat)
this.$emit('getAddressInfo',addressInfo)//拖动结束获取地址并传递给父组件
},
//通过地址查询经纬度
getLngLatFromAddress(address){
if(!address) return
let {cityInfo}=this
let {citycode}=cityInfo
return new Promise((resolve,reject)=>{
AMap.plugin('AMap.Geocoder', ()=> {
let geocoder = new AMap.Geocoder({
city:citycode
})
geocoder.getLocation(address, (status, result) =>{
let lngLatArr=[]
let {geocodes=[]} = result
geocodes.forEach((item,index)=>{
let {lng,lat}=item.location
lngLatArr.push({lng,lat})
})
resolve(lngLatArr)
})
})
})
},
//搜索提示
getSearchAddresList(keyword){
let {cityInfo}=this
let {citycode}=cityInfo
return new Promise((resolve,reject)=>{
AMap.plugin('AMap.Autocomplete', ()=>{
// 实例化Autocomplete
let autoOptions = {
//city 限定城市,默认全国
city: citycode
}
let autoComplete= new AMap.Autocomplete(autoOptions);
autoComplete.search(keyword, (status, result)=> {
// 搜索成功时,result即是对应的匹配数据
if (status === 'complete' && result.info === 'OK') {
// result为对应的地理位置详细信息
resolve(result.tips)
}
})
})
})
}
},
created(){
this.mapCenter=this.center
},
mounted() {
}
}
</script>
下面css部分,高德地图组件本身默认没有宽高,需要继承父级的宽高,所以需要给el-map标签父级设置宽高
<style scoped lang="less">
.amapBox{
width:100%;
}
</style>
地图组件已经完成,可以愉快的调用了
父组件调用AMap组件
AMap已经配置为全局组件,所以本页面可以直接使用,不再需要引入和注册组件
<template>
<div class="mapBox columnStart">
<div class="mapSearchBox rowStart">
<img src="../../../assets/images/search.png" class="searchIcon"/>
<input placeholder="搜索地点" class="mapInput" v-model="searchName" @input="searchAddress"/>
</div>
<AMap @getAddressInfo="getAddressInfo" ref="amapComponent"/>
<ul class="mapAddressBox">
<li class="rowBtween mapAddressLi" v-for="(address,index) in addresses" :key="index" @click="chooseAddress(index)">
<div class="addressBox columnStart">
<div class="addressName">{{address.name}}</div>
<span class="detailAddress gray999">{{address.formattedAddress}}</span>
</div>
<van-icon name="success" color="#4491FA" size="18" v-if="activeIndex===index"/>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'ChooseAddress',
data() {
return {
routerData:{},//路由跳转携带点数据
activeIndex:null,//选择点地址下标
addresses:[],//搜索出来的地址
searchName:'',//要搜索的地址名称
fromRouteName:'',//来源路由名称
}
},
methods: {
//选择地址
chooseAddress(index){
this.activeIndex=index
},
//获取地址
getAddressInfo(addressInfo){
// console.log(addressInfo)
let {formattedAddress,province,city,district,township}=addressInfo
this.addresses=[
{
name:`${township}(${city}${district})`,
formattedAddress
}
]
this.activeIndex=0
},
//搜索地址
async searchAddress(){
let {searchName}=this
let addressInfos=await this.$refs.amapComponent.getSearchAddresList(searchName)
// console.log(addressInfos)
this.addresses=[]
for(let i=0;i<addressInfos.length;i++){
this.addresses.push({
name:addressInfos[i].name,
formattedAddress:`${addressInfos[i].district}${addressInfos[i].address}`
})
}
},
//确定选择地址
sureChooseAddress(){
let {addresses,activeIndex,routerData,fromRouteName}=this
routerData.mapAddressInfo=addresses[activeIndex]
this.$globalMethods.batchDispatchFun([
{fun:'changeShowRightBtn',data:false},
])
this.$router.replace({
name:fromRouteName,
params:{
routerData,
}
})
}
},
mounted() {
let {topTitle='地图',routerData={},fromRouteName=''} = this.$route.params
this.routerData=routerData
this.fromRouteName=fromRouteName
this.$globalMethods.batchDispatchFun([
{fun:'changeTopTitle',data:topTitle},
])
}
}
</script>
<style scoped lang="less">
.mapBox{
background:#f5f5f5;
.mapSearchBox{
width:7.1rem;
height:.7rem;
margin:.2rem auto;
background:#ffffff;
border:solid .01rem #cccccc;
-webkit-border-radius: .1rem;
-moz-border-radius: .1rem;
border-radius: .1rem;
padding:0 .2rem;
.searchIcon{
width:.36rem;
height:.36rem;
margin-right:.2rem;
}
.mapInput{
width:6rem;
border:none;
}
}
.mapAddressBox{
padding:0.2rem 0 1rem .2rem;
width:100%;
background:#ffffff;
height:5rem;
overflow:auto;
.mapAddressLi{
padding:.2rem 0.2rem .2rem 0;
border-bottom:solid .01rem #e6e6e6;
.addressBox{
align-items:flex-start;
.addressName{
max-width:6rem;
overflow:hidden;
-ms-text-overflow: ellipsis;
text-overflow: ellipsis;
white-space: nowrap;
}
.detailAddress{
margin-top:.1rem;
font-size:.24rem;
max-width:6rem;
overflow:hidden;
-ms-text-overflow: ellipsis;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
}
</style>
————————————————
版权声明:本文为CSDN博主「前端小菜鸟crazy yang」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41000974/article/details/105169669