How to Integrate AMap API in Vue for Positioning and Custom Info Windows
This guide walks through registering an AMap application, installing vue‑amap, configuring the API loader, building a reusable Vue component with search, geolocation, custom markers and styled info windows, and embedding the component into a page to achieve full map display and positioning functionality.
After setting up the RuoYi front‑end/back‑end project (see the linked CSDN tutorial), the next step is to add Gaode (AMap) map capabilities.
1. Register an AMap application
Log in to the AMap Open Platform, create a new Web application, and generate a key. The key will be used in the Vue configuration.
2. Install the Vue wrapper npm install vue-amap 3. Initialize the loader in main.js
<script>
import VueAMap from 'vue-amap'
Vue.use(VueAMap)
VueAMap.initAMapApiLoader({
key: 'YOUR_AMAP_KEY',
plugin: [
'AMap.Scale',
'AMap.OverView',
'AMap.ToolBar',
'AMap.MapType',
'AMap.PlaceSearch',
'AMap.Geolocation',
'AMap.Geocoder'
],
v: '1.4.4',
uiVersion: '1.0'
})
</script>4. Create the map component AMap.vue
The template defines a full‑size container, a search box, and buttons for manual search and positioning. The core map element is <el-amap> with bindings for manager, zoom, plugins, center, and events.
<template lang="html">
<div style="width:100%;height:800px;">
<div class="container">
<div class="search-box">
<input v-model="searchKey" type="search" id="search">
<button @click="searchByHand">搜索</button>
<div class="tip-box" id="searchTip"></div>
<button @click="positionByHand">定位</button>
</div>
<el-amap
:amap-manager="amapManager"
:vid="'amap-vue'"
:zoom="zoom"
:plugin="plugin"
:center="center"
:events="events"
class="amap-box">
<el-amap-marker
v-for="(marker, index) in carmarkers"
:key="index"
:position="marker.position"
:vid="index"
:content="marker.content"
:events="marker.events"></el-amap-marker>
<el-amap-info-window
:position="currentWindow.position"
:content="currentWindow.content"
:visible="currentWindow.visible"
:events="currentWindow.events">
</el-amap-info-window>
</el-amap>
</div>
</div>
</template>
<script>
import { AMapManager, lazyAMapApiLoaderInstance } from 'vue-amap'
let amapManager = new AMapManager()
export default {
name: 'AMap',
data() {
return {
carmarkers: [],
currentWindow: { position: [116.396624, 39.908167], content: '111', events: {}, visible: false },
address: null,
searchKey: '',
amapManager,
markers: [],
searchOption: { city: '全国', citylimit: true },
center: [116.396624, 39.908167],
zoom: 17,
lng: 0,
lat: 0,
loaded: false,
events: {
init() {
lazyAMapApiLoaderInstance.load().then(() => { this.initSearch() })
},
click(e) {
this.markers = []
const { lng, lat } = e.lnglat
this.lng = lng
this.lat = lat
this.center = [lng, lat]
this.markers.push([lng, lat])
const geocoder = new AMap.Geocoder({ radius: 1000, extensions: 'all' })
console.log(lng + "," + lat)
geocoder.getAddress([lng, lat], (status, result) => {
if (status === 'complete' && result.info === 'OK' && result && result.regeocode) {
console.log(result.regeocode.formattedAddress)
this.address = result.regeocode.formattedAddress
this.searchKey = result.regeocode.formattedAddress
this.$nextTick()
}
})
}
},
plugin: [
{ pName: 'Geocoder', events: { init(o) {} } },
{ pName: 'Geolocation', events: { init(o) { o.getCurrentPosition((status, result) => {
if (result && result.position) {
this.lng = result.position.lng
this.lat = result.position.lat
this.center = [this.lng, this.lat]
this.markers.push([this.lng, this.lat])
this.loaded = true
this.$nextTick()
}
}) } } },
{ pName: 'ToolBar', events: { init(instance) {} } },
{ pName: 'OverView', events: { init(instance) {} } },
{ pName: 'MapType', defaultType: 0, events: { init(instance) {} } },
{ pName: 'PlaceSearch', events: { init(instance) {} } }
]
}
},
methods: {
initSearch() {
const vm = this
const map = this.amapManager.getMap()
AMapUI.loadUI(['misc/PoiPicker'], function(PoiPicker) {
const poiPicker = new PoiPicker({
input: 'search',
placeSearchOptions: { map: map, pageSize: 10 },
suggestContainer: 'searchTip',
searchResultsContainer: 'searchTip'
})
vm.poiPicker = poiPicker
poiPicker.on('poiPicked', function(poiResult) {
const source = poiResult.source
const poi = poiResult.item
if (source !== 'search') {
poiPicker.searchByKeyword(poi.name)
} else {
poiPicker.clearSearchResults()
vm.markers = []
const lng = poi.location.lng
const lat = poi.location.lat
const address = poi.cityname + poi.adname + poi.name
vm.center = [lng, lat]
vm.markers.push([lng, lat])
vm.lng = lng
vm.lat = lat
vm.address = address
vm.searchKey = address
}
})
})
},
searchByHand() {
if (this.searchKey !== '') {
this.poiPicker.searchByKeyword(this.searchKey)
}
},
positionByHand() {
this.currentWindow = {
position: [121.492439, 31.233264],
content: `<div style="color: #1c84c6;">公众号:霸道的程序猿</div>`,
events: { close: e => { this.currentWindow.visible = false } },
visible: true
}
this.carmarkers = [{
position: [121.492439, 31.233264],
content: `<div><img width=50 height=50 src="https://images.cnblogs.com/cnblogs_com/badaoliumangqizhi/1539113/o_qrcode_for_gh_f76a8d7271eb_258.jpg" alt="汽车"></div>`,
events: { click: e => { this.currentWindow = { position: this.center, content: `<div style="color: #1c84c6;">公众号:霸道的程序猿 </div>`, events: { close: ev => { this.currentWindow.visible = false } }, visible: true } } }
}]
}
}
}
</script>
<style lang="css">
.container { width:100%; height:100%; position:relative; left:50%; top:50%; transform:translate3d(-50%,-50%,0); border:1px solid #999; }
.search-box { position:absolute; z-index:5; width:30%; left:13%; top:10px; height:30px; }
.search-box input { float:left; width:80%; height:100%; border:1px solid #30ccc1; padding:0 8px; outline:none; }
.search-box button { float:left; width:20%; height:100%; background:#30ccc1; border:1px solid #30ccc1; color:#fff; outline:none; }
.tip-box { width:100%; max-height:260px; position:absolute; top:30px; overflow-y:auto; background:#fff; }
</style>5. Use the component in a page
import AMap from '@/components/Amap/AMap'
export default {
name: 'index',
components: { AMap }
} <template>
<div class="app-container home">
<el-row :gutter="20">
<AMap/>
</el-row>
<el-divider />
</div>
</template>The page now displays the map with search, geolocation, custom markers, and a styled info window. Additional features can be explored in the official AMap documentation.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
The Dominant Programmer
Resources and tutorials for programmers' advanced learning journey. Advanced tracks in Java, Python, and C#. Blog: https://blog.csdn.net/badao_liumang_qizhi
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
