vue-amap安装和使用
之前分享了异步加载高德地图api的用法,现在记录一下vue-amap的用法。
vue-amap 是饿了么开源的一套基于 Vue 2.0 和高德地图的地图组件。 数据状态与地图状态单向绑定,开发者无需关心地图的具体操作。
官方文档:https://elemefe.github.io/vue-amap/#/zh-cn/introduction/install
步骤如下:
1.npm 安装
npm install vue-amap --save
如果是CDN方式,目前可通过unpkg.com/vue-amap获取最新版本的资源。
<script src="https://unpkg.com/vue-amap/dist/index.js"></script>
2.使用实例
实例需求描述:搜索并选择地址,选中后地图定位到该地址,并获取经纬度自动填入下方的输入框中。
注:实例中使用的框架是ElementUI,其表单组件使用比较方便。
实现步骤:
(1)安装后在main.js中设置以下内容:
import VueAMap from "vue-amap"; Vue.use(VueAMap); // 初始化vue-amap VueAMap.initAMapApiLoader({ key: "your key", // 这里写你申请的高德地图的key plugin: ["AMap.Autocomplete", "AMap.Geocoder", "AMap.Geolocation"], v: "1.4.15", uiVersion: "1.1" });
(2)定义地图搜索组件 base/mapSearch/baseMapSearch.vue
<template> <div> <div class="search-box"> <el-input v-model="searchKey" type="search" id="search" placeholder="请输入详细地址" ></el-input> <!--<button @click="searchByHand">搜索</button>--> <div class="tip-box" id="searchTip"></div> </div> <!-- amap-manager: 地图管理对象 vid:地图容器节点的ID zooms: 地图显示的缩放级别范围,在PC上,默认范围[3,18],取值范围[3-18];在移动设备上,默认范围[3-19],取值范围[3-19] center: 地图中心点坐标值 plugin:地图使用的插件 events: 事件 --> <div class="amap-box"> <el-amap :amap-manager="amapManager" :vid="'amap-vue'" :zoom="zoom" :plugin="plugin" :center="center" :events="events" > <!-- 标记 --> <el-amap-marker v-for="(marker, index) in markers" :position="marker" :key="index" ></el-amap-marker> </el-amap> </div> </div> </template> <script> import { AMapManager, lazyAMapApiLoaderInstance } from "vue-amap"; let amapManager = new AMapManager(); export default { props: ["city", "value", "longitude", "latitude", "isEdit"], data() { let self = this; return { address: null, searchKey: "", amapManager, markers: [], searchOption: { city: this.city ? this.city : "全国", citylimit: true }, center: [121.329402, 31.228667], zoom: 17, lng: 0, lat: 0, loaded: false, events: { init() { lazyAMapApiLoaderInstance.load().then(() => { self.initSearch(); }); }, // 点击获取地址的数据 click(e) { self.markers = []; let { lng, lat } = e.lnglat; self.lng = lng; self.lat = lat; self.center = [lng, lat]; self.markers.push([lng, lat]); // 这里通过高德 SDK 完成。 let geocoder = new AMap.Geocoder({ radius: 1000, extensions: "all" }); geocoder.getAddress([lng, lat], function(status, result) { if (status === "complete" && result.info === "OK") { if (result && result.regeocode) { self.address = result.regeocode.formattedAddress; self.searchKey = result.regeocode.formattedAddress; self.$emit("updateLocation", lng, lat, self.searchKey); self.$nextTick(); } } }); } }, // 一些工具插件 plugin: [ { // 定位 pName: "Geolocation", events: { init(o) { // o是高德地图定位插件实例 o.getCurrentPosition((status, result) => { if (result && result.position) { if (self.isEdit) { // 设置经度 self.lng = self.longitude; // 设置维度 self.lat = self.latitude; // 设置坐标 self.center = [self.longitude, self.latitude]; self.markers.push([self.longitude, self.latitude]); } else { // 设置经度 self.lng = result.position.lng; // 设置维度 self.lat = result.position.lat; // 设置坐标 self.center = [self.lng, self.lat]; self.markers.push([self.lng, self.lat]); } // load self.loaded = true; // 页面渲染好后 self.$nextTick(); } }); } } } ] }; }, created() { if (this.value) { this.searchKey = this.value; this.address = this.value; } if (this.longitude && this.latitude) { this.lng = this.longitude; this.lat = this.latitude; this.center = [this.longitude, this.latitude]; this.markers.push([this.longitude, this.latitude]); } }, methods: { // 选择地址后自动定位到当前地址附近 updateAddress(value, longitude, latitude) { this.searchKey = value; this.address = value; this.lng = longitude; this.lat = latitude; this.center = [longitude, latitude]; this.markers.push([longitude, latitude]); }, initSearch() { let vm = this; let map = this.amapManager.getMap(); AMapUI.loadUI(["misc/PoiPicker"], function(PoiPicker) { let poiPicker = new PoiPicker({ input: "search", placeSearchOptions: { map: map, pageSize: 10 }, suggestContainer: "searchTip", searchResultsContainer: "searchTip" }); vm.poiPicker = poiPicker; // 监听poi选中信息 poiPicker.on("poiPicked", function(poiResult) { let source = poiResult.source; let poi = poiResult.item; if (source !== "search") { poiPicker.searchByKeyword(poi.name); } else { poiPicker.clearSearchResults(); vm.markers = []; let lng = poi.location.lng; let lat = poi.location.lat; let address = poi.name; // 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; vm.$emit("updateLocation", lng, lat, vm.searchKey); } }); }); }, searchByHand() { if (this.searchKey !== "" && this.poiPicker) { this.poiPicker.searchByKeyword(this.searchKey); } } } }; </script> <style lang="stylus"> .search-box { margin-top: 6px; width: 100%; } .search-box input { padding: 0 15px; width: 100%; height: 32px; line-height: 32px; color: #606266; border: 1px solid #dcdfe6; border-radius: 4px; } .search-box input:focus { border-color: #409eff; outline: 0; } .search-box input::-webkit-input-placeholder { color: #c0c4cc; } .tip-box { width: 100%; max-height:280px; position: absolute; top: 72px; z-index: 10000; overflow-y: auto; background-color: #fff; } </style> <style> .amap-ui-poi-picker-sugg, .amap_lib_placeSearch { border: 1px solid #eee; border-radius: 4px; } .amap-box { height: 200px; } </style>
这里样式使用了stylus,可自行转换其他样式。
(3)在组件中使用地图搜索组件,这里以弹窗为例
<template> <el-dialog :title="title" :visible.sync="visible" :before-close="handleClose" width="600px" append-to-body :close-on-click-modal="false" :close-on-press-escape="false" > <div class="form-info"> <el-form :model="form" ref="form" :rules="rules" size="small" label-width="110px" > <el-form-item label="选择地址" prop="address"> <base-map-search ref="mapSearch" :city="form.city" :value="form.address" :longitude="form.addLon" :latitude="form.addLat" :isEdit="isEdit" @updateLocation="updateLocation" /> </el-form-item> <el-row> <el-col :span="12"> <el-form-item prop="addLon" label="经度"> <el-input v-model.number="form.addLon" :maxlength="15" placeholder="请输入经度" ></el-input> </el-form-item> </el-col> <el-col :span="12" class="right-label-form-item"> <el-form-item prop="addLat" label="纬度"> <el-input v-model.number="form.addLat" :maxlength="15" placeholder="请输入纬度" ></el-input> </el-form-item> </el-col> </el-row> </el-form> </div> </el-dialog> </template> <script> import BaseMapSearch from "../base/mapSearch/baseMapSearch"; export default { props: ["visible", "isEdit", "detail"], components: { BaseMapSearch }, data() { return { title: "添加地址", form: { address: "", addLon: "", addLat: "" }, rules: { address: [ { required: true, message: "请输入地址", trigger: ["blur", "change"] } ], addLat: [ { required: true, message: "请输入纬度", trigger: ["blur", "change"] } ], addLon: [ { required: true, message: "请输入经度", trigger: ["blur", "change"] } ], } }; }, created() { if (this.isEdit) { this.initForm(); } }, methods: { // 初始化表单 initForm() { this.title = "修改地址"; if (this.detail) { this.form = { ...this.detail }; } }, // 地图搜索选址 updateLocation(lng, lat, address) { this.form.addLon = lng; this.form.addLat = lat; this.form.address = address; }, handleClose() { this.$emit("update:visible", false); } } }; </script>
(4)这时,如果项目中使用了ESlint,会报AMap、AMapUI未定义的错误,我们需要在.eslintrc.js文件中定义globals属性:
module.exports = { // ... globals: { AMap: false, AMapUI: false } };
这样就写好了,效果如图: