vue 使用高德地图插件 vue-amap文章

账号注册

首先得成为高德地图开发者,也就是说你的拥有一个账号,当然有公司账号最好,没有就暂时自己先注册一个。

注册好后,点开控制台,右上角创建一个新应用,选好你需要的环境,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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容